* Public License as described at http://www.gnu.org/licenses/gpl.txt
*/
-#include "mail-functions.h"
-#include "wrappers.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
-#include <sys/stat.h>
#include <fcntl.h>
+#include "mail-functions.h"
+#include "wrappers.h"
#include "log_error.h"
/* "HELO \r\n " has length 7 */
}
-int write_mailbody_from_fd(int sockfd, int fd)
+int write_mailbody_from_map(int sockfd, char *mapstart, size_t size)
{
- char buf[WRITE_BUFSIZE+3];
- size_t len, bytes_written;
- char *bufp;
- int full_line = 1; /* true, if last write included a newline */
-
- /* Zero the buffer */
- memset(buf, 0, sizeof(buf));
-
- /* Read from beginning of the file */
-
- if(lseek(fd, 0L, SEEK_SET) < 0) {
- log_error(LOG_ARGS, "lseek() failed");
- return errno;
- }
-
- /* keep writing chunks of line (max WRITE_BUFSIZE) */
- for(;;) {
- bufp = buf+1;
-
- len = read(fd, bufp, WRITE_BUFSIZE);
-
- if(len == 0)
- return 0;
-
- if(len < 0) {
- if (errno == EINTR) {
- continue;
- } else {
- return errno;
+ char *cur, *next;
+ char newlinebuf[3];
+ size_t len;
+
+ for(next = cur = mapstart; next < mapstart + size; next++) {
+ if(*next == '\n') {
+ if(writen(sockfd, cur, next - cur) < 0) {
+ log_error(LOG_ARGS, "Could not write mail");
+ return -1;
}
+ newlinebuf[0] = '\r';
+ newlinebuf[1] = '\n';
+ len = 2;
+ if(*(next+1) == '.') {
+ newlinebuf[2] = '.';
+ len = 3;
+ }
+ if(writen(sockfd, newlinebuf, len) < 0) {
+ log_error(LOG_ARGS, "Could not write mail");
+ return -1;
+ }
+ cur = next + 1;
}
-
- /* fix "dot lines" */
- if(full_line && (bufp[0] == '.')) {
- *(--bufp) = '.';
- len++;
- }
-
- /* fix newlines */
- if((len > 0) && (bufp[len-1] == '\n')) {
- bufp[len-1] = '\r';
- bufp[len] = '\n';
- bufp[len+1] = 0;
- len++;
- full_line = 1;
- } else {
- full_line = 0;
- }
-
-#if 0
- fprintf(stderr, "write_mailbody_from_file = [%s]\n", bufp);
-#endif
- bytes_written = writen(sockfd, bufp, len);
- if(bytes_written < 0 )
- return errno;
}
return 0;
#include <unistd.h>
#include <errno.h>
#include <string.h>
-#include <strings.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <libgen.h>
#include <syslog.h>
#include <stdarg.h>
+#include <sys/mman.h>
#include "mlmmj-send.h"
#include "mlmmj.h"
}
int send_mail(int sockfd, const char *from, const char *to,
- const char *replyto, int mailfd,
+ const char *replyto, char *mailmap, size_t mailsize,
const char *listdir, const char *mlmmjbounce)
{
int retval = 0;
char *reply;
-
+
retval = write_mail_from(sockfd, from);
if(retval) {
log_error(LOG_ARGS, "Could not write MAIL FROM\n");
}
}
- retval = write_mailbody_from_fd(sockfd, mailfd);
+ retval = write_mailbody_from_map(sockfd, mailmap, mailsize);
if(retval) {
log_error(LOG_ARGS, "Could not write mailbody\n");
return retval;
}
int send_mail_many(int sockfd, const char *from, const char *replyto,
- int mailfd, int subfd, const char *listaddr,
- const char *archivefilename, const char *listdir,
- const char *mlmmjbounce)
+ char *mailmap, size_t mailsize, int subfd,
+ const char *listaddr, const char *archivefilename,
+ const char *listdir, const char *mlmmjbounce)
{
int sendres = 0, addrfd;
char *bounceaddr, *addr, *index, *dirname, *addrfilename;
chomp(addr);
if(from)
sendres = send_mail(sockfd, from, addr, replyto,
- mailfd, listdir, NULL);
+ mailmap, mailsize, listdir, NULL);
else {
bounceaddr = bounce_from_adr(addr, listaddr,
archivefilename);
sendres = send_mail(sockfd, bounceaddr, addr, replyto,
- mailfd, listdir, mlmmjbounce);
+ mailmap, mailsize, listdir, mlmmjbounce);
free(bounceaddr);
}
if(sendres && listaddr && archivefilename) {
char *replyto = NULL, *bounceaddr = NULL, *to_addr = NULL;
char *relayhost = NULL, *archivefilename = NULL, *tmpstr;
char *listctrl = NULL, *subddirname = NULL, *listdir = NULL;
- char *mlmmjbounce = NULL, *bindir;
+ char *mlmmjbounce = NULL, *bindir, *mailmap;
DIR *subddir;
struct dirent *dp;
+ struct stat st;
log_set_name(argv[0]);
exit(EXIT_FAILURE);
}
+ if(fstat(mailfd, &st) < 0) {
+ log_error(LOG_ARGS, "Could not stat mailfd");
+ exit(EXIT_FAILURE);
+ }
+
+ mailmap = mmap(0, st.st_size, PROT_READ, MAP_SHARED, mailfd, 0);
+ if(mailmap == (void *)-1) {
+ log_error(LOG_ARGS, "Could not mmap mailfd");
+ exit(EXIT_FAILURE);
+ }
+
switch(listctrl[0]) {
case '1': /* A single mail is to be sent, do nothing */
break;
switch(listctrl[0]) {
case '1': /* A single mail is to be sent */
initsmtp(&sockfd, relayhost);
- sendres = send_mail(sockfd, bounceaddr, to_addr,
- replyto, mailfd, listdir, NULL);
+ sendres = send_mail(sockfd, bounceaddr, to_addr, replyto,
+ mailmap, st.st_size, listdir, NULL);
endsmtp(&sockfd);
if(sendres) {
/* error, so keep it in the queue */
break;
case '2': /* Moderators */
initsmtp(&sockfd, relayhost);
- if(send_mail_many(sockfd, bounceaddr, NULL, mailfd, subfd,
- NULL, NULL, listdir, NULL))
+ if(send_mail_many(sockfd, bounceaddr, NULL, mailmap, st.st_size,
+ subfd, NULL, NULL, listdir, NULL))
close(sockfd);
else
endsmtp(&sockfd);
break;
case '3': /* resending earlier failed mails */
initsmtp(&sockfd, relayhost);
- if(send_mail_many(sockfd, NULL, NULL, mailfd, subfd,
- listaddr, mailfilename, listdir, mlmmjbounce))
+ if(send_mail_many(sockfd, NULL, NULL, mailmap, st.st_size,
+ subfd, listaddr, mailfilename, listdir,
+ mlmmjbounce))
close(sockfd);
else
endsmtp(&sockfd);
free(subfilename);
initsmtp(&sockfd, relayhost);
- sendres = send_mail_many(sockfd, NULL, NULL, mailfd,
- subfd, listaddr, archivefilename,
- listdir, mlmmjbounce);
+ sendres = send_mail_many(sockfd, NULL, NULL, mailmap,
+ st.st_size, subfd, listaddr,
+ archivefilename, listdir, mlmmjbounce);
if (sendres) {
/* If send_mail_many() failed we close the
* connection to the mail server in a brutal
break;
}
+ munmap(mailmap, st.st_size);
+ close(mailfd);
+
if(archive) {
rename(mailfilename, archivefilename);
free(archivefilename);
} else if(deletewhensent)
unlink(mailfilename);
- close(mailfd);
return EXIT_SUCCESS;
}