]> git.ipfire.org Git - thirdparty/mlmmj.git/commitdiff
send_mail: huge simplification using stdio
authorBaptiste Daroussin <bapt@FreeBSD.org>
Tue, 14 Feb 2023 14:03:55 +0000 (15:03 +0100)
committerBaptiste Daroussin <bapt@FreeBSD.org>
Tue, 14 Feb 2023 14:03:55 +0000 (15:03 +0100)
Use stdio instead of mmap or inmemory buffers. This is easier to test,
easier to read, and the previous mecanism was not signigicantly faster

include/mail-functions.h
include/send_mail.h
src/mail-functions.c
src/mlmmj-send.c
src/send_mail.c
src/utils.c
tests/mlmmj.c

index 221b3bb3c55056efccf7af647156e064acce3aa8..6e2fd4e8b8b143854a74fcc38ac7c1e3e9304dbb 100644 (file)
@@ -1,6 +1,6 @@
-/* Copyright (C) 2002, 2003 Mads Martin Joergensen <mmj at mmj.dk>
- *
- * $Id$
+/*
+ * Copyright (C) 2002, 2003 Mads Martin Joergensen <mmj at mmj.dk>
+ * Copyright (C) 2023 Mads Martin Joergensen <mmj at mmj.dk>
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to
@@ -21,8 +21,7 @@
  * IN THE SOFTWARE.
  */
 
-#ifndef MAIL_FUNCTIONS_H
-#define MAIL_FUNCTIONS_H
+#pragma once
 
 #define WRITE_BUFSIZE 1024
 
@@ -33,16 +32,9 @@ int write_ehlo(int sockfd, const char *hostname);
 int write_mail_from(int sockfd, const char *from_addr, const char *extra);
 int write_rcpt_to(int sockfd, const char *rcpt_addr);
 int write_custom_line(int sockfd, const char *line);
-int write_mailbody_from_map(int sockfd, char *mailmap, size_t mailsize,
-                           const char *tohdr);
 void write_mailbody(int sockfd, FILE *fp, const char *tohdr);
-char *get_preppedhdrs_from_map(char *mapstart, size_t maplen, size_t *hdrslen);
-char *get_prepped_mailbody_from_map(char *mapstart, size_t size,
-                                   size_t *bodylen);
 int write_replyto(int sockfd, const char *replyaddr);
 int write_dot(int sockfd);
 int write_quit(int sockfd);
 int write_data(int sockfd);
 int write_rset(int sockfd);
-
-#endif /* MAIL_FUNCTIONS_H */
index a7945c42f94bda921f8d211495a696c0696a3803..04d1447c3c4e134c413a4ae6f3e89bb329e1d1bb 100644 (file)
@@ -33,11 +33,6 @@ struct mail {
        const char *to;
        const char *replyto;
        FILE *fp;
-       char *map;
-       size_t size;
-       char *hdrs;
-       char *body;
-       bool inmem;
        bool addtohdr;
 };
 
index 215aead26d62c3dc1c83df6c85e2d36fb8400cef..393885ce808b66be44ba6b8638b76c95a8fd80bf 100644 (file)
@@ -78,46 +78,6 @@ int write_rcpt_to(int sockfd, const char *rcpt_addr)
        return (write_sock(sockfd, "TO", "RCPT TO:<%s>\r\n", rcpt_addr));
 }
 
-int write_mailbody_from_map(int sockfd, char *mapstart, size_t size,
-                           const char *tohdr)
-{
-       char *cur, *next;
-       char newlinebuf[3];
-       size_t len;
-       int i = 1;
-
-       for(next = cur = mapstart; next < mapstart + size; next++) {
-               if(*next == '\n') {
-                       if(dprintf(sockfd, "%.*s", (int)(next - cur), cur) < 0) {
-                               log_error(LOG_ARGS, "Could not write mail");
-                               return -1;
-                       }
-                       newlinebuf[0] = '\r';
-                       newlinebuf[1] = '\n';
-                       len = 2;
-                       if(next < (mapstart + size - 1) && *(next+1) == '.') {
-                               newlinebuf[2] = '.';
-                               len++;
-                       }
-                       if(dprintf(sockfd, "%.*s", (int)len, newlinebuf) < 0) {
-                               log_error(LOG_ARGS, "Could not write mail");
-                               return -1;
-                       }
-                       if(i && tohdr && *(next+1) == '\n') { /* add To: header */
-                               if(dprintf(sockfd, "To: %s\r\n", tohdr) < 0) {
-                                       log_error(LOG_ARGS, "Could not write"
-                                                           " To: header");
-                                       return -1;
-                               }
-                               i = 0; /* Make sure we don't write it again */
-                       }
-                       cur = next + 1;
-               }
-       }
-
-       return 0;
-}
-
 void
 write_mailbody(int sockfd, FILE *fp, const char *tohdr)
 {
@@ -138,87 +98,6 @@ write_mailbody(int sockfd, FILE *fp, const char *tohdr)
        }
 }
 
-char *get_preppedhdrs_from_map(char *mapstart, size_t maplen, size_t *hlen)
-{
-       char *cur, *next, *endhdrs, *retstr, *r;
-       const char newlinebuf[] = "\r\n";
-       size_t hdrlen, n = 0;
-
-       endhdrs = strnstr(mapstart, "\n\n", maplen);
-       if(endhdrs == NULL)
-               return NULL; /* The map doesn't map a file with a mail */
-
-       hdrlen = endhdrs - mapstart + 1;
-
-       for(next = cur = mapstart; next < mapstart + hdrlen; next++)
-               if(*next == '\n')
-                       n++;
-
-       retstr = xmalloc(hdrlen + n + 1);
-       *hlen = hdrlen + n;     
-       r = retstr;     
-
-       for(next = cur = mapstart; next < mapstart + hdrlen; next++) {
-               if(*next == '\n') {
-                       strncpy(r, cur, next - cur);
-                       r += next - cur;
-                       strncpy(r, newlinebuf, 2);
-                       r += 2;
-                       cur = next + 1;
-               }
-       }
-       retstr[*hlen] = '\0';
-
-       return retstr;
-}
-
-char *get_prepped_mailbody_from_map(char *mapstart, size_t size, size_t *blen)
-{
-       char *cur, *next, *endhdrs, *retstr, *r;
-       char newlinebuf[3];
-       size_t bodylen, len, n = 0;
-
-       endhdrs = strnstr(mapstart, "\n\n", size);
-       if(endhdrs == NULL)
-               return NULL; /* The map doesn't map a file with a mail */
-
-       endhdrs++; /* Skip the first newline, it's in hdrs */
-
-       bodylen = size - (endhdrs - mapstart);
-       
-       for(next = cur = endhdrs; next < mapstart + size; next++) {
-               if(*next == '\n') {
-                       n++;
-                       if((next < mapstart + size - 1) && *(next+1) == '.')
-                               n++;
-               }
-       }
-
-       retstr = xmalloc(bodylen + n +1);
-       *blen = bodylen + n;
-       r = retstr;
-       
-       for(next = cur = endhdrs; next < mapstart + size; next++) {
-               if(*next == '\n') {
-                       strncpy(r, cur, next - cur);
-                       r += next - cur;
-                       newlinebuf[0] = '\r';
-                       newlinebuf[1] = '\n';
-                       len = 2;
-                       if((next < mapstart + size - 1) && *(next+1) == '.') {
-                               newlinebuf[2] = '.';
-                               len = 3;
-                       }
-                       strncpy(r, newlinebuf, len);
-                       r += len;
-                       cur = next + 1;
-               }
-       }
-       retstr[*blen] = '\0';
-
-       return retstr;
-}
-
 int write_dot(int sockfd)
 {
        return write_sock(sockfd, "", "\r\n.\r\n");
index 984d988439dbe35f48e0b3f279fdebabe6c1888a..7ace0b1101c2499b49bc047c3d1954762a18b714 100644 (file)
@@ -234,24 +234,7 @@ int send_mail_verp(int sockfd, strlist *addrs, struct mail *mail,
                return MLMMJ_DATA;
        }
 
-       if(mail->inmem) {
-               retval = dprintf(sockfd, "%s", mail->hdrs);
-               if(retval < 0) {
-                       log_error(LOG_ARGS, "Could not write mailheaders.\n");
-                       return retval;
-               }
-               retval = dprintf(sockfd, "%s", mail->body);
-               if(retval < 0) {
-                       log_error(LOG_ARGS, "Could not write mailbody.\n");
-                       return retval;
-               }
-       } else {
-               retval = write_mailbody_from_map(sockfd, mail->map, mail->size, NULL);
-               if(retval) {
-                       log_error(LOG_ARGS, "Could not write mail\n");
-                       return retval;
-               }
-       }
+       write_mailbody(sockfd, mail->fp, NULL);
 
        retval = write_dot(sockfd);
        if(retval) {
@@ -426,8 +409,7 @@ static void print_help(const char *prg)
 
 int main(int argc, char **argv)
 {
-       size_t hdrslen, bodylen;
-       int sockfd = -1, mailfd = 0, opt, mindex = 0, subfd = 0, tmpfd;
+       int sockfd = -1, opt, mindex = 0, subfd = 0, tmpfd;
        int deletewhensent = 1, sendres = 0, digest = 0;
        bool archive = true, ctrlarchive;
        int res;
@@ -439,7 +421,6 @@ int main(int argc, char **argv)
        char *verp = NULL;
        char *verpfrom;
        char *reply, *smtphelo, *requeuefilename;
-       ssize_t memmailsize = 0;
        DIR *subddir;
        struct dirent *dp;
        struct stat st;
@@ -448,7 +429,7 @@ int main(int argc, char **argv)
        struct sigaction sigact;
        struct mail mail;
        struct ml ml;
-       int subdirfd;
+       int subdirfd, mailfd;
 
        memset(&mail, 0, sizeof(mail));
        log_set_name(argv[0]);
@@ -544,50 +525,15 @@ int main(int argc, char **argv)
 
        /* initialize file with mail to send */
 
-       if((mailfd = open(mailfilename, O_RDWR, 0644)) < 0 &&
+       if ((mailfd = open(mailfilename, O_RDWR)) == -1 ||
            !lock(mailfd, true)) {
-               log_error(LOG_ARGS, "Could not open '%s'", mailfilename);
-               exit(EXIT_FAILURE);
-       }
-
-       if(fstat(mailfd, &st) < 0) {
-               log_error(LOG_ARGS, "Could not stat mailfd");
+               log_error(LOG_ARGS, "Could not open '%s'", mailfilename);
                exit(EXIT_FAILURE);
        }
+       mail.fp = fdopen(mailfd, "r");
 
-       if (ml.dir) {
-               memmailsize = ctrlsizet(ml.ctrlfd, "memorymailsize", MEMORYMAILSIZE);
+       if (ml.dir)
                ctrlarchive = statctrl(ml.ctrlfd, "noarchive");
-       }
-
-       if(st.st_size > memmailsize) {
-               errno = 0;
-               log_error(LOG_ARGS, "Not preparing in memory. "
-                                   "Mail is %ld bytes", (long)st.st_size);
-       } else
-               mail.inmem = true;
-
-       mail.map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, mailfd, 0);
-       if(mail.map == MAP_FAILED) {
-               log_error(LOG_ARGS, "Could not mmap mailfd");
-               exit(EXIT_FAILURE);
-       }
-       mail.size = st.st_size;
-
-       if(mail.inmem) {
-               mail.hdrs = get_preppedhdrs_from_map(mail.map, mail.size, &hdrslen);
-               if(mail.hdrs == NULL) {
-                       log_error(LOG_ARGS, "Could not prepare headers");
-                       exit(EXIT_FAILURE);
-               }
-               mail.body = get_prepped_mailbody_from_map(mail.map, st.st_size,
-                                                    &bodylen);
-               if(mail.body == NULL) {
-                       log_error(LOG_ARGS, "Could not prepare mailbody");
-                       free(mail.hdrs);
-                       exit(EXIT_FAILURE);
-               }
-       }
 
        switch(listctrl) {
        case '1': /* A single mail is to be sent, do nothing */
@@ -599,8 +545,6 @@ int main(int argc, char **argv)
                if((subfd = openat(ml.ctrlfd, "moderators", O_RDONLY)) < 0) {
                        log_error(LOG_ARGS, "Could not open '%s':",
                                            subfilename);
-                       free(mail.hdrs);
-                       free(mail.body);
                        /* No moderators is no error. Could be the sysadmin
                         * likes to do it manually.
                         */
@@ -613,8 +557,6 @@ int main(int argc, char **argv)
                if((subfd = open(subfilename, O_RDONLY)) < 0) {
                        log_error(LOG_ARGS, "Could not open '%s':",
                                            subfilename);
-                       free(mail.hdrs);
-                       free(mail.body);
                        exit(EXIT_FAILURE);
                }
                break;
@@ -753,8 +695,6 @@ int main(int argc, char **argv)
                if (subdirfd == -1 || (subddir = fdopendir(subdirfd)) == NULL) {
                        log_error(LOG_ARGS, "Could not opendir(%s/%s)", ml.dir,
                                            subddirname);
-                       free(mail.hdrs);
-                       free(mail.body);
                        exit(EXIT_FAILURE);
                }
 
@@ -881,11 +821,7 @@ int main(int argc, char **argv)
                closedir(subddir);
                break;
        }
-       
-       free(mail.hdrs);
-       free(mail.body);
-       munmap(mail.map, mail.size);
-       close(mailfd);
+
        free(verp);
        free(smtphelo);
 
index f2aa80e8fd45e97d53c8c79912564d8997566beb..c558019e091958fedc746cbe9bc7447eb8ab0148 100644 (file)
@@ -253,17 +253,6 @@ send_mail(int sockfd, struct mail *mail, int listfd, int ctrlfd, bool bounce)
                return 0;
        }
 
-       if (mail->inmem) {
-               if (mail->hdrs == NULL || mail->body == NULL) {
-                       log_error(LOG_ARGS, "No body or headers");
-                       return (0);
-               }
-       } else if (mail->fp == NULL) {
-               if (mail->size == 0 || mail->map == NULL) {
-                       log_error(LOG_ARGS, "No mmap mail");
-                       return (0);
-               }
-       }
        retval = write_mail_from(sockfd, mail->from, "");
        if(retval) {
                log_error(LOG_ARGS, "Could not write MAIL FROM\n");
@@ -326,34 +315,7 @@ send_mail(int sockfd, struct mail *mail, int listfd, int ctrlfd, bool bounce)
                }
        }
 
-       if(mail->inmem) {
-               retval = dprintf(sockfd, "%s", mail->hdrs);
-               if(retval < 0) {
-                       log_error(LOG_ARGS, "Could not write mailheaders.\n");
-                       return retval;
-               }
-               if(mail->addtohdr) {
-                       retval = dprintf(sockfd, "To: %s\r\n", mail->to);
-                       if(retval < 0) {
-                               log_error(LOG_ARGS, "Could not write To:.\n");
-                               return retval;
-                       }
-               }
-               retval = dprintf(sockfd, "%s", mail->body);
-               if(retval < 0) {
-                       log_error(LOG_ARGS, "Could not write mailbody.\n");
-                       return retval;
-               }
-       } else if (mail->fp != NULL) {
-               write_mailbody(sockfd, mail->fp, mail->addtohdr ? mail->to : NULL);
-       } else {
-               retval = write_mailbody_from_map(sockfd, mail->map, mail->size,
-                   mail->addtohdr ? mail->to : NULL);
-               if(retval) {
-                       log_error(LOG_ARGS, "Could not write mail\n");
-                       return retval;
-               }
-       }
+       write_mailbody(sockfd, mail->fp, mail->addtohdr ? mail->to : NULL);
 
        retval = write_dot(sockfd);
        if(retval) {
index ff6a73fe6cdfc120c1ed949a02c6864529510cd7..abf96c99a9b61993fd4bb2d96a634de6aa2e80ca 100644 (file)
@@ -208,7 +208,13 @@ lock(int fd, bool wr)
        lck.l_whence = SEEK_SET;
        lck.l_start = 0;
        lck.l_len = 0;
+       int i = 0;
        do {
+               i++;
+               if (i == 2) {
+                       warn("plop");
+                       exit(1);
+               }
                r = fcntl(fd, F_SETLKW, &lck);
        } while (r < 0 && errno != EINTR);
        if (r == -1) {
index a6558f09bcc19fe82c69831c33782594911b0adc..23d5df7716978c73dd5226e0ad9573f16d501902 100644 (file)
@@ -85,7 +85,6 @@ ATF_TC_WITHOUT_HEAD(write_rset);
 ATF_TC_WITHOUT_HEAD(write_replyto);
 ATF_TC_WITHOUT_HEAD(write_rcpt_to);
 ATF_TC_WITHOUT_HEAD(write_mail_from);
-ATF_TC_WITHOUT_HEAD(write_mailbody_from_map);
 ATF_TC_WITHOUT_HEAD(write_mailbody);
 ATF_TC_WITHOUT_HEAD(strtotimet);
 ATF_TC_WITHOUT_HEAD(decode_qp);
@@ -102,15 +101,8 @@ ATF_TC_WITHOUT_HEAD(smtp_bad_ehlo);
 ATF_TC_WITHOUT_HEAD(smtp_no_ehlo);
 ATF_TC_WITHOUT_HEAD(endsmtp);
 ATF_TC_WITHOUT_HEAD(do_bouncemail);
-ATF_TC_WITHOUT_HEAD(send_mail_0);
-ATF_TC_WITHOUT_HEAD(send_mail_1);
-ATF_TC_WITHOUT_HEAD(send_mail_2);
-ATF_TC_WITHOUT_HEAD(send_mail_3);
-ATF_TC_WITHOUT_HEAD(send_mail_4);
-ATF_TC_WITHOUT_HEAD(send_mail_5);
-ATF_TC_WITHOUT_HEAD(send_mail_6);
-ATF_TC_WITHOUT_HEAD(send_mail_7);
-ATF_TC_WITHOUT_HEAD(send_mail_8);
+ATF_TC_WITHOUT_HEAD(send_mail_basics);
+ATF_TC_WITHOUT_HEAD(send_mail);
 ATF_TC_WITHOUT_HEAD(getlistdelim);
 ATF_TC_WITHOUT_HEAD(getlistdelim_0);
 ATF_TC_WITHOUT_HEAD(getlistdelim_1);
@@ -127,10 +119,6 @@ ATF_TC_WITHOUT_HEAD(copy_file_2);
 ATF_TC_WITHOUT_HEAD(controls);
 ATF_TC_WITHOUT_HEAD(incindexfile);
 ATF_TC_WITHOUT_HEAD(log_oper);
-ATF_TC_WITHOUT_HEAD(get_preppedhdrs_from_map);
-ATF_TC_WITHOUT_HEAD(get_preppedhdrs_from_map_1);
-ATF_TC_WITHOUT_HEAD(get_prepped_mailbody_from_map);
-ATF_TC_WITHOUT_HEAD(get_prepped_mailbody_from_map_1);
 ATF_TC_WITHOUT_HEAD(get_ctrl_command);
 ATF_TC_WITHOUT_HEAD(get_recipextra_from_env_none);
 ATF_TC_WITHOUT_HEAD(get_recipextra_from_env_qmail);
@@ -557,112 +545,6 @@ ATF_TC_BODY(write_mail_from, tc)
        }
 }
 
-ATF_TC_BODY(write_mailbody_from_map, tc)
-{
-       /* no new lines: ignore */
-       struct stat st;
-       char *start;
-       atf_utils_create_file("myemailbody.txt", "line");
-       int fd1 = open("myemailbody.txt", O_RDONLY);
-       fstat(fd1, &st);
-       ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
-       int fd = open("out.txt", O_CREAT|O_WRONLY, 0644);
-       ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
-       close(fd);
-       munmap(start, st.st_size);
-       close(fd1);
-       if (!atf_utils_compare_file("out.txt", "")) {
-               atf_utils_cat_file("out.txt", ">");
-               atf_tc_fail("Unexpected output");
-       }
-
-       /* With a single new line */
-       atf_utils_create_file("myemailbody.txt", "line\n");
-       fd1 = open("myemailbody.txt", O_RDONLY);
-       fstat(fd1, &st);
-       ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
-       fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
-       ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
-       close(fd);
-       munmap(start, st.st_size);
-       close(fd1);
-       if (!atf_utils_compare_file("out.txt", "line\r\n")) {
-               atf_utils_cat_file("out.txt", ">");
-               atf_tc_fail("Unexpected output");
-       }
-
-       /* With a single new line with a . */
-       atf_utils_create_file("myemailbody.txt", "line\n.");
-       fd1 = open("myemailbody.txt", O_RDONLY);
-       fstat(fd1, &st);
-       ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
-       fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
-       ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
-       close(fd);
-       munmap(start, st.st_size);
-       close(fd1);
-       if (!atf_utils_compare_file("out.txt", "line\r\n.")) {
-               atf_utils_cat_file("out.txt", ">");
-               atf_tc_fail("Unexpected output");
-       }
-
-       /* With a single new line, 2 new lines */
-       atf_utils_create_file("myemailbody.txt", "line\n\n");
-       fd1 = open("myemailbody.txt", O_RDONLY);
-       fstat(fd1, &st);
-       ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
-       fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
-       ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
-       close(fd);
-       munmap(start, st.st_size);
-       close(fd1);
-       if (!atf_utils_compare_file("out.txt", "line\r\nTo: test@plop.meh\r\n\r\n")) {
-               atf_utils_cat_file("out.txt", ">");
-               atf_tc_fail("Unexpected output");
-       }
-
-
-       /* With a single 2 lines separated by 2 new lines*/
-       atf_utils_create_file("myemailbody.txt", "line\n\nline2\n\n");
-       fd1 = open("myemailbody.txt", O_RDONLY);
-       fstat(fd1, &st);
-       ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
-       fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
-       ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, "test@plop.meh"), 0);
-       close(fd);
-       munmap(start, st.st_size);
-       close(fd1);
-       if (!atf_utils_compare_file("out.txt", "line\r\nTo: test@plop.meh\r\n\r\nline2\r\n\r\n")) {
-               atf_utils_cat_file("out.txt", ">");
-               atf_tc_fail("Unexpected output");
-       }
-
-
-       /* No to header */
-       atf_utils_create_file("myemailbody.txt", "line\n\nline2\n\n");
-       fd1 = open("myemailbody.txt", O_RDONLY);
-       fstat(fd1, &st);
-       ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
-       fd = open("out.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
-       ATF_REQUIRE_EQ(write_mailbody_from_map(fd, start, st.st_size, NULL), 0);
-       close(fd);
-       munmap(start, st.st_size);
-       close(fd1);
-       if (!atf_utils_compare_file("out.txt", "line\r\n\r\nline2\r\n\r\n")) {
-               atf_utils_cat_file("out.txt", ">");
-               atf_tc_fail("Unexpected output");
-       }
-
-       /* With invalid socket */
-       atf_utils_create_file("myemailbody.txt", "line\n");
-       fd1 = open("myemailbody.txt", O_RDONLY);
-       fstat(fd1, &st);
-       ATF_REQUIRE((start = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd1, 0)) != NULL);
-       ATF_REQUIRE_EQ(write_mailbody_from_map(-1, start, st.st_size, "test@plop.meh"), -1);
-       munmap(start, st.st_size);
-       close(fd1);
-}
-
 ATF_TC_BODY(write_mailbody, tc)
 {
        /* no new lines: ignore */
@@ -1221,150 +1103,17 @@ ATF_TC_BODY(do_bouncemail, tc)
        close(ctrlfd);
 }
 
-ATF_TC_BODY(send_mail_0, tc)
-{
-       int smtppipe[2];
-       struct mail mail = {};
-       ATF_REQUIRE_EQ(send_mail(-1, NULL, -1, -1, false), EBADF);
-       ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
-       pid_t p = atf_utils_fork();
-       if (p == 0) {
-               const char *replies [] = {
-                       "550 2.1.0 kO\n",
-                       NULL,
-               };
-               read_print_reply(smtppipe[0], replies, NELEM(replies));
-               exit(0);
-       }
-       close(smtppipe[0]);
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       mail.to = "plop@meh";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       mail.from = "test@meh";
-       mail.inmem = true;
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       mail.hdrs = "plop";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       mail.hdrs = NULL;
-       mail.body = "body";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       mail.inmem = false;
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       mail.size = 1;
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       mail.size = 0;
-       mail.map = "bla";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       mail.inmem = true;
-       mail.hdrs = "headers";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), MLMMJ_FROM);
-       atf_utils_wait(p, 0, "MAIL FROM:<test@meh>\r\nRSET\r\n", "");
-}
-
-ATF_TC_BODY(send_mail_1, tc)
+ATF_TC_BODY(send_mail_basics, tc)
 {
-       int smtppipe[2];
        struct mail mail = {};
-       ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
-       pid_t p = atf_utils_fork();
-       if (p == 0) {
-               const char *replies [] = {
-                       "250 2.1.0 Ok\n",
-                       "550 2.1.0 OK\n",
-                       NULL,
-               };
-               read_print_reply(smtppipe[0], replies, NELEM(replies));
-               exit(0);
-       }
-       close(smtppipe[0]);
+       ATF_REQUIRE_EQ_MSG(send_mail(1, &mail, -1, -1, false), 0, "Failure with to == NULL");
+       mail.to = "plop";
+       ATF_REQUIRE_EQ_MSG(send_mail(1, &mail, -1, -1, false), 0, "Failure with to without @");
        mail.to = "plop@meh";
-       mail.from = "test@meh";
-       mail.inmem = true;
-       mail.hdrs = "headers";
-       mail.body = "body";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), MLMMJ_RCPTTO);
-       atf_utils_wait(p, 0, "MAIL FROM:<test@meh>\r\nRCPT TO:<plop@meh>\r\nRSET\r\n", "");
+       ATF_REQUIRE_EQ_MSG(send_mail(1, &mail, -1, -1, false), 0, "Failure with from == NULL");
 }
 
-ATF_TC_BODY(send_mail_2, tc)
-{
-       int smtppipe[2];
-       struct mail mail = {};
-       ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
-       pid_t p = atf_utils_fork();
-       if (p == 0) {
-               const char *replies [] = {
-                       "250 2.1.0 Ok\n",
-                       "250 2.1.0 OK\n",
-                       "550 2.1.0 OK\n",
-                       NULL,
-               };
-               read_print_reply(smtppipe[0], replies, NELEM(replies));
-               exit(0);
-       }
-       close(smtppipe[0]);
-       mail.to = "plop@meh";
-       mail.from = "test@meh";
-       mail.inmem = true;
-       mail.hdrs = "headers";
-       mail.body = "body";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), MLMMJ_DATA);
-       atf_utils_wait(p, 0, "MAIL FROM:<test@meh>\r\nRCPT TO:<plop@meh>\r\nDATA\r\nRSET\r\n", "");
-}
-
-ATF_TC_BODY(send_mail_3, tc)
-{
-       int smtppipe[2];
-       struct mail mail = {};
-       ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
-       pid_t p = atf_utils_fork();
-       if (p == 0) {
-               const char *replies [] = {
-                       "250 2.1.0 Ok\n",
-                       "250 2.1.0 OK\n",
-                       "550 2.1.0 OK\n",
-                       NULL,
-               };
-               read_print_reply(smtppipe[0], replies, NELEM(replies));
-               exit(0);
-       }
-       close(smtppipe[0]);
-       mail.to = "plop@meh";
-       mail.from = "test@meh";
-       mail.inmem = true;
-       mail.hdrs = "headers";
-       mail.body = "body";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), MLMMJ_DATA);
-       atf_utils_wait(p, 0, "MAIL FROM:<test@meh>\r\nRCPT TO:<plop@meh>\r\nDATA\r\nRSET\r\n", "");
-}
-
-ATF_TC_BODY(send_mail_4, tc)
-{
-       int smtppipe[2];
-       struct mail mail = {};
-       ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
-       pid_t p = atf_utils_fork();
-       if (p == 0) {
-               const char *replies [] = {
-                       "250 2.1.0 OK\n",
-                       "250 2.1.0 OK\n",
-                       "250 2.1.0 OK\n",
-                       NULL,
-               };
-               read_print_reply(smtppipe[0], replies, NELEM(replies));
-               exit(0);
-       }
-       close(smtppipe[0]);
-       mail.to = "plop@meh";
-       mail.from = "test@meh";
-       mail.inmem = true;
-       mail.hdrs = "headers";
-       mail.body = "body";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), MLMMJ_DATA);
-       atf_utils_wait(p, 0, "MAIL FROM:<test@meh>\r\nRCPT TO:<plop@meh>\r\nDATA\r\nRSET\r\n", "");
-}
-
-ATF_TC_BODY(send_mail_5, tc)
+ATF_TC_BODY(send_mail, tc)
 {
        int smtppipe[2];
        struct mail mail = {};
@@ -1378,35 +1127,6 @@ ATF_TC_BODY(send_mail_5, tc)
                        NULL,
                        NULL,
                        NULL,
-                       "350 2.1.0 OK\n",
-                       NULL,
-               };
-               read_print_reply(smtppipe[0], replies, NELEM(replies));
-               exit(0);
-       }
-       close(smtppipe[0]);
-       mail.to = "plop@meh";
-       mail.from = "test@meh";
-       mail.inmem = true;
-       mail.hdrs = "headers\n";
-       mail.body = "body\n";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), MLMMJ_DOT);
-       atf_utils_wait(p, 0, "MAIL FROM:<test@meh>\r\nRCPT TO:<plop@meh>\r\nDATA\r\nheaders\nbody\n\r\n.\r\nRSET\r\n", "");
-}
-
-ATF_TC_BODY(send_mail_6, tc)
-{
-       int smtppipe[2];
-       struct mail mail = {};
-       ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
-       pid_t p = atf_utils_fork();
-       if (p == 0) {
-               const char *replies [] = {
-                       "250 2.1.0 OK\n",
-                       "250 2.1.0 OK\n",
-                       "350 2.1.0 OK\n",
-                       NULL,
-                       NULL,
                        NULL,
                        NULL,
                        "250 2.1.0 OK\n",
@@ -1417,70 +1137,6 @@ ATF_TC_BODY(send_mail_6, tc)
        close(smtppipe[0]);
        mail.to = "plop@meh";
        mail.from = "test@meh";
-       mail.inmem = true;
-       mail.hdrs = "headers\n";
-       mail.body = "body\n";
-       mail.replyto= "yeah@meh";
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       atf_utils_wait(p, 0, "MAIL FROM:<test@meh>\r\nRCPT TO:<plop@meh>\r\nDATA\r\nReply-To: yeah@meh\r\nheaders\nbody\n\r\n.\r\n", "");
-}
-
-ATF_TC_BODY(send_mail_7, tc)
-{
-       int smtppipe[2];
-       struct mail mail = {};
-       ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
-       pid_t p = atf_utils_fork();
-       if (p == 0) {
-               const char *replies [] = {
-                       "250 2.1.0 OK\n",
-                       "250 2.1.0 OK\n",
-                       "350 2.1.0 OK\n",
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL,
-                       "250 2.1.0 OK\n",
-               };
-               read_print_reply(smtppipe[0], replies, NELEM(replies));
-               exit(0);
-       }
-       close(smtppipe[0]);
-       mail.to = "plop@meh";
-       mail.from = "test@meh";
-       mail.inmem = true;
-       mail.hdrs = "headers\n";
-       mail.body = "body\n";
-       mail.addtohdr = true;
-       ATF_REQUIRE_EQ(send_mail(smtppipe[1], &mail, -1, -1, false), 0);
-       atf_utils_wait(p, 0, "MAIL FROM:<test@meh>\r\nRCPT TO:<plop@meh>\r\nDATA\r\nheaders\nTo: plop@meh\r\nbody\n\r\n.\r\n", "");
-}
-
-ATF_TC_BODY(send_mail_8, tc)
-{
-       int smtppipe[2];
-       struct mail mail = {};
-       ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
-       pid_t p = atf_utils_fork();
-       if (p == 0) {
-               const char *replies [] = {
-                       "250 2.1.0 OK\n",
-                       "250 2.1.0 OK\n",
-                       "350 2.1.0 OK\n",
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL,
-                       NULL,
-                       "250 2.1.0 OK\n",
-               };
-               read_print_reply(smtppipe[0], replies, NELEM(replies));
-               exit(0);
-       }
-       close(smtppipe[0]);
-       mail.to = "plop@meh";
-       mail.from = "test@meh";
-       mail.inmem = false;
        atf_utils_create_file("mymail.txt", "headers\n\nbody\n");
        mail.fp = fopen("mymail.txt", "r");
        mail.addtohdr = true;
@@ -1725,78 +1381,6 @@ ATF_TC_BODY(log_oper, tc)
        }
 }
 
-ATF_TC_BODY(get_preppedhdrs_from_map, tc)
-{
-       struct stat st;
-       char *hdr;
-       atf_utils_create_file("./mailfile", "head1: plop\nhead2\n\nbody\n");
-
-       stat("./mailfile", &st);
-       int fd = open("./mailfile", O_RDONLY);
-       ATF_REQUIRE(fd != -1);
-       char *map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
-       ATF_REQUIRE(map != NULL);
-       size_t len = 0;
-       ATF_REQUIRE((hdr = get_preppedhdrs_from_map(map, st.st_size, &len)) != NULL);
-       ATF_REQUIRE_EQ(len, 20);
-       ATF_REQUIRE(strncmp(hdr, "head1: plop\r\nhead2\r\n", len) == 0);
-       ATF_REQUIRE_STREQ(hdr, "head1: plop\r\nhead2\r\n");
-       munmap(map, st.st_size);
-       close(fd);
-}
-
-ATF_TC_BODY(get_preppedhdrs_from_map_1, tc)
-{
-       struct stat st;
-       atf_utils_create_file("./mailfile", "head1: plop\nhead2\nbody\n");
-
-       stat("./mailfile", &st);
-       int fd = open("./mailfile", O_RDONLY);
-       ATF_REQUIRE(fd != -1);
-       char *map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
-       ATF_REQUIRE(map != NULL);
-       size_t len = 0;
-       ATF_REQUIRE(get_preppedhdrs_from_map(map, st.st_size, &len) == NULL);
-       munmap(map, st.st_size);
-       close(fd);
-}
-
-ATF_TC_BODY(get_prepped_mailbody_from_map, tc)
-{
-       struct stat st;
-       char *body;
-       atf_utils_create_file("./mailfile", "head1: plop\nhead2\n\nbody\n");
-
-       stat("./mailfile", &st);
-       int fd = open("./mailfile", O_RDONLY);
-       ATF_REQUIRE(fd != -1);
-       char *map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
-       ATF_REQUIRE(map != NULL);
-       size_t len = 0;
-       ATF_REQUIRE((body = get_prepped_mailbody_from_map(map, st.st_size, &len)) != NULL);
-       ATF_REQUIRE_EQ(len, 8);
-       ATF_REQUIRE(strncmp(body, "\r\nbody\r\n", len) == 0);
-       ATF_REQUIRE_STREQ(body, "\r\nbody\r\n");
-       munmap(map, st.st_size);
-       close(fd);
-}
-
-ATF_TC_BODY(get_prepped_mailbody_from_map_1, tc)
-{
-       struct stat st;
-       atf_utils_create_file("./mailfile", "head1: plop\nhead2\nbody\n");
-
-       stat("./mailfile", &st);
-       int fd = open("./mailfile", O_RDONLY);
-       ATF_REQUIRE(fd != -1);
-       char *map = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
-       ATF_REQUIRE(map != NULL);
-       size_t len = 0;
-       ATF_REQUIRE(get_prepped_mailbody_from_map(map, st.st_size, &len) == NULL);
-       munmap(map, st.st_size);
-       close(fd);
-}
-
 ATF_TC_BODY(get_ctrl_command, tc)
 {
        char *param = NULL;
@@ -2457,7 +2041,6 @@ ATF_TP_ADD_TCS(tp)
        ATF_TP_ADD_TC(tp, write_replyto);
        ATF_TP_ADD_TC(tp, write_rcpt_to);
        ATF_TP_ADD_TC(tp, write_mail_from);
-       ATF_TP_ADD_TC(tp, write_mailbody_from_map);
        ATF_TP_ADD_TC(tp, write_mailbody);
        ATF_TP_ADD_TC(tp, strtotimet);
        ATF_TP_ADD_TC(tp, decode_qp);
@@ -2474,15 +2057,8 @@ ATF_TP_ADD_TCS(tp)
        ATF_TP_ADD_TC(tp, smtp_no_ehlo);
        ATF_TP_ADD_TC(tp, endsmtp);
        ATF_TP_ADD_TC(tp, do_bouncemail);
-       ATF_TP_ADD_TC(tp, send_mail_0);
-       ATF_TP_ADD_TC(tp, send_mail_1);
-       ATF_TP_ADD_TC(tp, send_mail_2);
-       ATF_TP_ADD_TC(tp, send_mail_3);
-       ATF_TP_ADD_TC(tp, send_mail_4);
-       ATF_TP_ADD_TC(tp, send_mail_5);
-       ATF_TP_ADD_TC(tp, send_mail_6);
-       ATF_TP_ADD_TC(tp, send_mail_7);
-       ATF_TP_ADD_TC(tp, send_mail_8);
+       ATF_TP_ADD_TC(tp, send_mail_basics);
+       ATF_TP_ADD_TC(tp, send_mail);
        ATF_TP_ADD_TC(tp, getlistdelim);
        ATF_TP_ADD_TC(tp, getlistdelim_0);
        ATF_TP_ADD_TC(tp, getlistdelim_1);
@@ -2499,10 +2075,6 @@ ATF_TP_ADD_TCS(tp)
        ATF_TP_ADD_TC(tp, controls);
        ATF_TP_ADD_TC(tp, incindexfile);
        ATF_TP_ADD_TC(tp, log_oper);
-       ATF_TP_ADD_TC(tp, get_preppedhdrs_from_map);
-       ATF_TP_ADD_TC(tp, get_preppedhdrs_from_map_1);
-       ATF_TP_ADD_TC(tp, get_prepped_mailbody_from_map);
-       ATF_TP_ADD_TC(tp, get_prepped_mailbody_from_map_1);
        ATF_TP_ADD_TC(tp, get_ctrl_command);
        ATF_TP_ADD_TC(tp, get_recipextra_from_env_none);
        ATF_TP_ADD_TC(tp, get_recipextra_from_env_qmail);