char **values;
};
+struct queuedmail {
+ int fd;
+ char *name;
+};
+
/* Has to go here, since it's used in many places */
enum subtype {
void mlmmj_list_init(struct mlmmj_list *list);
bool mlmmj_list_open(struct mlmmj_list *list);
void mlmmj_list_close(struct mlmmj_list *list);
+void queuedmail_free(struct queuedmail *q);
+struct queuedmail *queuedmail_new(void);
#define MY_ASSERT(expression) if (!(expression)) { \
errno = 0; \
char *get_processed_text_line(text *txt, int headers, struct mlmmj_list *list);
char *prepstdreply(text *txt, struct mlmmj_list *list,
const char *from, const char *to, const char *replyto, bool infd);
+struct queuedmail *prepqstdreply(text *txt, struct mlmmj_list *list,
+ const char *from, const char *to, const char *replyto);
void close_text(text *txt);
#endif /* PREPSTDREPLY_H */
#include "mlmmj.h"
-void send_help(struct mlmmj_list *list, const char *queuefilename,
+void send_help(struct mlmmj_list *list, struct queuedmail *q,
const char *emailaddr);
#endif
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);
-bool send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, int queue, const char *mailfilename);
+bool send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, struct queuedmail *q);
#endif
struct strlist *owners;
int owner_idx;
text *txt;
- char *queuefilename;
-
+ struct queuedmail *q;
+
/* A closed list doesn't allow subscribtion and unsubscription */
closedlist = statctrl(list, "closedlist");
MY_ASSERT(txt);
register_unformatted(txt, "subaddr",
fromemails->emaillist[0]);
- queuefilename = prepstdreply(txt, list, "$listowner$",
- fromemails->emaillist[0], NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$listowner$",
+ fromemails->emaillist[0], NULL);
+ MY_ASSERT(q);
close_text(txt);
- send_help(list, queuefilename, fromemails->emaillist[0]);
- return -1;
+ send_help(list, q, fromemails->emaillist[0]);
+ /* send_help does not return */
}
log_oper(list->dir, OPLOGFNAME, "mlmmj-sub: request for digest"
" subscription from %s",
MY_ASSERT(txt);
register_unformatted(txt, "subaddr",
fromemails->emaillist[0]);
- queuefilename = prepstdreply(txt, list, "$listowner$",
- fromemails->emaillist[0], NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$listowner$",
+ fromemails->emaillist[0], NULL);
+ MY_ASSERT(q);
close_text(txt);
- send_help(list, queuefilename, fromemails->emaillist[0]);
+ send_help(list, q, fromemails->emaillist[0]);
return -1;
}
log_oper(list->dir, OPLOGFNAME, "mlmmj-sub: request for nomail"
MY_ASSERT(txt);
register_unformatted(txt, "subaddr",
fromemails->emaillist[0]);
- queuefilename = prepstdreply(txt, list, "$listowner$",
- fromemails->emaillist[0], NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$listowner$",
+ fromemails->emaillist[0], NULL);
+ MY_ASSERT(q);
close_text(txt);
- send_help(list, queuefilename, fromemails->emaillist[0]);
+ send_help(list, q, fromemails->emaillist[0]);
return -1;
}
log_oper(list->dir, OPLOGFNAME, "mlmmj-sub: request for both"
fromemails->emaillist[0]);
txt = open_text(list, "help", NULL, NULL, NULL, "listhelp");
MY_ASSERT(txt);
- queuefilename = prepstdreply(txt, list,
- "$listowner$", fromemails->emaillist[0], NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list,
+ "$listowner$", fromemails->emaillist[0], NULL);
+ MY_ASSERT(q);
close_text(txt);
- send_help(list, queuefilename, fromemails->emaillist[0]);
+ send_help(list, q, fromemails->emaillist[0]);
break;
/* listname+faq@domain.tld */
fromemails->emaillist[0]);
txt = open_text(list, "faq", NULL, NULL, NULL, "listfaq");
MY_ASSERT(txt);
- queuefilename = prepstdreply(txt, list,
- "$listowner$", fromemails->emaillist[0], NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list,
+ "$listowner$", fromemails->emaillist[0], NULL);
+ MY_ASSERT(q);
close_text(txt);
- send_help(list, queuefilename, fromemails->emaillist[0]);
+ send_help(list, q, fromemails->emaillist[0]);
break;
/* listname+get-INDEX@domain.tld */
{
DIR *queuedir;
struct dirent *dp;
- char *mailname, *fromname, *toname, *reptoname, *from, *to, *repto;
+ char *fromname, *toname, *reptoname, *from, *to, *repto;
char *ch;
struct stat st;
int fromfd, tofd, fd, err = 0;
- int queuefd;
time_t t, bouncelife = 0;
+ struct queuedmail q;
if((queuedir = fdopendir(list->queuefd)) == NULL) {
log_error(LOG_ARGS, "Could not queue directory");
}
while((dp = readdir(queuedir)) != NULL) {
- mailname = dp->d_name;
- queuefd = openat(list->queuefd, mailname, O_RDONLY);
- if(queuefd < 0 || fstat(queuefd, &st) < 0) {
- log_error(LOG_ARGS, "Could not open or fstat(%s)", mailname);
+ q.name = dp->d_name;
+ q.fd = openat(list->queuefd, q.name, O_RDONLY);
+ if(q.fd < 0 || fstat(q.fd, &st) < 0) {
+ log_error(LOG_ARGS, "Could not open or fstat(%s)", q.name);
continue;
}
- if(!S_ISREG(st.st_mode))
+ if(!S_ISREG(st.st_mode)) {
+ close(q.fd);
continue;
+ }
if(strchr(dp->d_name, '.')) {
char *tmpname = xstrdup(dp->d_name);
ch = strrchr(tmpname, '.');
MY_ASSERT(ch);
*ch = '\0';
+ close(q.fd);
/* delete orphaned sidecar files */
if (fstatat(list->queuefd, tmpname, &st, 0) < 0) {
if(errno == ENOENT)
- unlinkat(list->queuefd, mailname, 0);
+ unlinkat(list->queuefd, q.name, 0);
}
free(tmpname);
continue;
}
- xasprintf(&fromname, "%s.mailfrom", mailname);
- xasprintf(&toname, "%s.reciptto", mailname);
- xasprintf(&reptoname, "%s.reply-to", mailname);
+ xasprintf(&fromname, "%s.mailfrom", q.name);
+ xasprintf(&toname, "%s.reciptto", q.name);
+ xasprintf(&reptoname, "%s.reply-to", q.name);
fromfd = openat(list->queuefd, fromname, O_RDONLY);
if(fromfd < 0)
mail currently being sent */
t = time(NULL);
if(t - st.st_mtime > (time_t)36000) {
- unlinkat(list->queuefd, mailname, 0);
+ unlinkat(list->queuefd, q.name, 0);
/* avoid leaving orphans */
unlinkat(list->queuefd, fromname, 0);
unlinkat(list->queuefd, toname, 0);
close(fromfd);
if(tofd >= 0)
close(tofd);
+ close(q.fd);
continue;
}
t = time(NULL);
if(t - st.st_mtime > bouncelife) {
- unlinkat(list->queuefd, mailname, 0);
+ unlinkat(list->queuefd, q.name, 0);
+ close(q.fd);
free(from);
free(to);
free(repto);
mh.to = to;
mh.from = from;
mh.replyto = repto;
- if (send_single_mail(list, &mh, queuefd, mailname))
+ if (send_single_mail(list, &mh, &q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
const char *efromismod = NULL;
const char *mailbasename = mybasename(mailfilename);
char *to, *reject;
- int notifymod = 0, status, queuefd;
+ int notifymod = 0, status;
pid_t childpid, pid;
+ struct queuedmail *q;
#if 0
printf("mailfilename = [%s], mailbasename = [%s]\n", mailfilename,
mailbasename);
finish_memory_lines(mls);
if(efromismod) {
+ struct queuedmail myq;
memset(&mh, 0, sizeof(mh));
mh.to = efromsender;
mh.from = from;
- queuefd = openat(list->queuefd, queuefilename,
- O_RDONLY);
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ myq.name = queuefilename;
+ myq.fd = openat(list->queuefd, myq.name, O_RDONLY);
+ if (send_single_mail(list, &mh, &myq))
exit(EXIT_SUCCESS);
} else
execlp(mlmmjsend, mlmmjsend,
register_formatted(txt, "moderators",
rewind_memory_lines, get_memory_line, mls);
register_originalmail(txt, mailfilename);
- queuefilename = prepstdreply(txt, list, "$listowner$", efromsender, NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$listowner$", efromsender, NULL);
+ MY_ASSERT(q);
close_text(txt);
finish_memory_lines(mls);
- queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
memset(&mh, 0, sizeof(mh));
mh.to = efromsender;
mh.from = from;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
char *causestr, const char *posteraddr, const char *subject,
char *donemailname, const char *mailfile)
{
- char *fromaddr, *queuefilename;
+ char *fromaddr;
text *txt;
struct mail_headers mh;
- int queuefd;
+ struct queuedmail *q;
xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn);
txt = open_text(list, "deny", "post", cause, NULL, subcause);
if (causestr != NULL)
register_unformatted(txt, cause, causestr);
register_originalmail(txt, donemailname);
- queuefilename = prepstdreply(txt, list, "$listowner$", posteraddr, NULL, false);
- MY_ASSERT(queuefilename);
- queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
+ q = prepqstdreply(txt, list, "$listowner$", posteraddr, NULL);
+ MY_ASSERT(q);
close_text(txt);
unlink(donemailname);
unlink(mailfile);
memset(&mh, 0, sizeof(mh));
mh.to = posteraddr;
mh.from = fromaddr;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
const char *modetype;
struct strlist *submods;
pid_t childpid, pid;
+ struct queuedmail *q;
/* generate the file in moderation/ */
switch(typesub) {
register_unformatted(txt, "moderators", "%gatekeepers"); /* DEPRECATED */
register_formatted(txt, "gatekeepers",
rewind_memory_lines, get_memory_line, mls);
- queuefilename = prepstdreply(txt, list, "$listowner$", subaddr, NULL, false);
+ q = prepqstdreply(txt, list, "$listowner$", subaddr, NULL);
MY_ASSERT(queuefilename);
close_text(txt);
finish_memory_lines(mls);
- int queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
struct mail_headers mh;
memset(&mh, 0, sizeof(mh));
mh.to = subaddr;
mh.from = from;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
enum subtype typesub, enum subreason reasonsub)
{
text *txt;
- char *queuefilename, *fromaddr, *listtext;
+ char *fromaddr, *listtext;
+ struct queuedmail *q;
xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim,
list->fqdn);
free(listtext);
MY_ASSERT(txt);
register_unformatted(txt, "subaddr", subaddr);
- queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, NULL, true);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$helpaddr$", subaddr, NULL);
+ MY_ASSERT(q);
close_text(txt);
- int queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
struct mail_headers mh;
memset(&mh, 0, sizeof(mh));
mh.to = subaddr;
mh.from = fromaddr;
- send_single_mail(list, &mh, queuefd, queuefilename);
+ send_single_mail(list, &mh, q);
+ queuedmail_free(q);
}
static void notify_sub(struct mlmmj_list *list, const char *subaddr,
{
char *fromaddr, *tostr;
text *txt;
- char *queuefilename = NULL, *listtext = NULL;
+ struct queuedmail *q;
+ char *listtext = NULL;
xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim,
list->fqdn);
MY_ASSERT(txt);
register_unformatted(txt, "subaddr", subaddr);
register_unformatted(txt, "newsub", subaddr); /* DEPRECATED */
- queuefilename = prepstdreply(txt, list, "$listowner$", "$listowner$", NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$listowner$", "$listowner$", NULL);
+ MY_ASSERT(q);
close_text(txt);
- int queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
struct mail_headers mh;
memset(&mh, 0, sizeof(mh));
mh.to = subaddr;
mh.from = fromaddr;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
int subconffd;
char *confirmaddr, *confirmfilename = NULL;
text *txt;
- char *listtext, *queuefilename = NULL, *fromaddr;
+ char *listtext, *fromaddr;
char *randomstr = NULL, *tmpstr;
+ struct queuedmail *q;
do {
free(confirmfilename);
register_unformatted(txt, "subaddr", subaddr);
register_unformatted(txt, "confaddr", confirmaddr); /* DEPRECATED */
register_unformatted(txt, "confirmaddr", confirmaddr);
- queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, confirmaddr, true);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$helpaddr$", subaddr, confirmaddr);
+ MY_ASSERT(q);
close_text(txt);
- int queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
struct mail_headers mh;
memset(&mh, 0, sizeof(mh));
mh.to = subaddr;
mh.from = fromaddr;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
enum subtype typesub)
{
text *txt;
- char *queuefilename, *fromaddr;
+ char *fromaddr;
+ struct queuedmail *q;
xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim,
list->fqdn);
"sub-subscribed");
MY_ASSERT(txt);
register_unformatted(txt, "subaddr", subaddr);
- queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$helpaddr$", subaddr, NULL);
+ MY_ASSERT(q);
close_text(txt);
- int queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
struct mail_headers mh;
memset(&mh, 0, sizeof(mh));
mh.to = subaddr;
mh.from = fromaddr;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
enum subtype typesub, enum subreason reasonsub)
{
text *txt;
- char *queuefilename, *fromaddr, *listtext;
+ char *fromaddr, *listtext;
+ struct queuedmail *q;
xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn);
free(listtext);
MY_ASSERT(txt);
register_unformatted(txt, "subaddr", subaddr);
- queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$helpaddr$", subaddr, NULL);
+ MY_ASSERT(q);
close_text(txt);
- int queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
struct mail_headers mh;
memset(&mh, 0, sizeof(mh));
mh.to = subaddr;
mh.from = fromaddr;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
{
char *fromaddr, *tostr;
text *txt;
- char *queuefilename = NULL;
const char *listtext;
+ struct queuedmail *q;
xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim,
list->fqdn);
MY_ASSERT(txt);
register_unformatted(txt, "subaddr", subaddr);
register_unformatted(txt, "oldsub", subaddr); /* DEPRECATED */
- queuefilename = prepstdreply(txt, list, "$listowner$", "$listowner$", NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$listowner$", "$listowner$", NULL);
+ MY_ASSERT(q);
close_text(txt);
- int queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
struct mail_headers mh;
memset(&mh, 0, sizeof(mh));
mh.to = tostr;
mh.from = fromaddr;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
const char *tmpstr;
char *confirmaddr;
text *txt;
- char *queuefilename, *fromaddr;
+ char *fromaddr;
char *randomstr = NULL, *confirmfilename = NULL, *listtext;
int subconffd;
+ struct queuedmail *q;
do {
free(confirmfilename);
register_unformatted(txt, "subaddr", subaddr);
register_unformatted(txt, "confaddr", confirmaddr); /* DEPRECATED */
register_unformatted(txt, "confirmaddr", confirmaddr);
- queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, confirmaddr, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$helpaddr$", subaddr, confirmaddr);
+ MY_ASSERT(q);
close_text(txt);
- int queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
struct mail_headers mh;
memset(&mh, 0, sizeof(mh));
mh.to = subaddr;
mh.from = fromaddr;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
enum subtype typesub)
{
text *txt;
- char *queuefilename, *fromaddr;
+ char *fromaddr;
+ struct queuedmail *q;
xasprintf(&fromaddr, "%s%sbounes-help@%s", list->name, list->delim, list->fqdn);
"unsub-notsubscribed");
MY_ASSERT(txt);
register_unformatted(txt, "subaddr", subaddr);
- queuefilename = prepstdreply(txt, list, "$helpaddr$", subaddr, NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$helpaddr$", subaddr, NULL);
+ MY_ASSERT(q);
close_text(txt);
- int queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
struct mail_headers mh;
memset(&mh, 0, sizeof(mh));
mh.to = subaddr;
mh.from = fromaddr;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
}
return (true);
}
+
+void
+queuedmail_free(struct queuedmail *q)
+{
+ if (q == NULL)
+ return;
+ free(q->name);
+ if (q->fd != -1)
+ close(q->fd);
+ free(q);
+}
+
+struct queuedmail *
+queuedmail_new(void)
+{
+ struct queuedmail *q = xcalloc(1, sizeof(struct queuedmail));
+ q->fd = -1;
+ return (q);
+}
return NULL;
}
- for (i=0; i<6; i++) {
+ for (i=0; i<6; i++) {
tmp = xstrdup("randomN");
tmp[6] = '0' + i;
str = random_str();
freeandreturn:
return retstr;
}
+
+struct queuedmail *prepqstdreply(text *txt, struct mlmmj_list *list,
+ const char *from, const char *to,
+ const char *replyto)
+{
+ size_t len, i;
+ char *line;
+ char *str;
+ char *tmp;
+ char *headers[10] = { NULL }; /* relies on NULL to flag end */
+ struct queuedmail *q = xcalloc(1, sizeof(struct queuedmail));
+
+ do {
+ if (list->queuefd == -1)
+ list->queuefd = openat(list->fd, "queue", O_DIRECTORY);
+ free(q->name);
+ q->name = random_str();
+ q->fd = openat(list->queuefd, q->name, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
+ } while ((q->fd < 0) && (errno == EEXIST));
+
+ if(q->fd < 0) {
+ log_error(LOG_ARGS, "Could not open std mail %s", q->name);
+ queuedmail_free(q);
+ return NULL;
+ }
+
+ for (i=0; i<6; i++) {
+ tmp = xstrdup("randomN");
+ tmp[6] = '0' + i;
+ str = random_str();
+ register_unformatted(txt, tmp, str);
+ free(tmp);
+ free(str);
+ }
+
+ tmp = substitute(from, list, txt);
+ xasprintf(&headers[0], "From: %s", tmp);
+ free(tmp);
+ tmp = substitute(to, list, txt);
+ xasprintf(&headers[1], "To: %s", tmp);
+ free(tmp);
+ headers[2] = genmsgid(list->fqdn);
+ chomp(headers[2]);
+ headers[3] = gendatestr();
+ chomp(headers[3]);
+ headers[4] = xstrdup("Subject: mlmmj administrivia");
+ headers[5] = xstrdup("MIME-Version: 1.0");
+ headers[6] = xstrdup("Content-Type: text/plain; charset=utf-8");
+ headers[7] = xstrdup("Content-Transfer-Encoding: 8bit");
+
+ if(replyto) {
+ tmp = substitute(replyto, list, txt);
+ xasprintf(&headers[8], "Reply-To: %s", tmp);
+ free(tmp);
+ }
+
+ for(;;) {
+ line = get_processed_text_line(txt, 1, list);
+ if (!line) {
+ log_error(LOG_ARGS, "No body in listtext");
+ break;
+ }
+ if (*line == '\0') {
+ /* end of headers */
+ free(line);
+ line = NULL;
+ break;
+ }
+ if (*line == ' ' || *line == '\t') {
+ /* line beginning with linear whitespace is a
+ continuation of previous header line */
+ if(dprintf(q->fd, "%s\n", line) < 0) {
+ log_error(LOG_ARGS, "Could not write std mail");
+ free(line);
+ queuedmail_free(q);
+ return (NULL);
+ }
+ } else {
+ tmp = line;
+ len = 0;
+ while (*tmp && *tmp != ':') {
+ tmp++;
+ len++;
+ }
+ if (!*tmp) {
+ log_error(LOG_ARGS, "No headers or invalid "
+ "header in listtext");
+ break;
+ }
+ tmp++;
+ len++;
+ /* remove the standard header if one matches */
+ for (i=0; headers[i] != NULL; i++) {
+ if (strncasecmp(line, headers[i], len) == 0) {
+ free(headers[i]);
+ while (headers[i] != NULL) {
+ headers[i] = headers[i+1];
+ i++;
+ }
+ break;
+ }
+ }
+ if (strncasecmp(line, "Subject:", len) == 0) {
+ tmp = unistr_utf8_to_header(tmp);
+ free(line);
+ xasprintf(&line, "Subject: %s", tmp);
+ free(tmp);
+ }
+ if(dprintf(q->fd, "%s\n", line) < 0) {
+ log_error(LOG_ARGS, "Could not write std mail");
+ free(line);
+ queuedmail_free(q);
+ return (NULL);
+ }
+ }
+ free(line);
+ line = NULL;
+ }
+
+ for (i=0; headers[i] != NULL; i++) {
+ if(dprintf(q->fd, "%s\n", headers[i]) < 0) {
+ log_error(LOG_ARGS, "Could not write std mail");
+ if (line)
+ free(line);
+ queuedmail_free(q);
+ return (NULL);
+ }
+ }
+
+ /* end the headers */
+ if(dprintf(q->fd, "\n") < 0) {
+ log_error(LOG_ARGS, "Could not write std mail");
+ if (line)
+ free(line);
+ queuedmail_free(q);
+ return (NULL);
+ }
+
+ if (line == NULL) {
+ line = get_processed_text_line(txt, 0, list);
+ }
+ while(line) {
+ if(dprintf(q->fd, "%s\n", line) < 0) {
+ free(str);
+ log_error(LOG_ARGS, "Could not write std mail");
+ queuedmail_free(q);
+ return (NULL);
+ }
+ free(line);
+ line = get_processed_text_line(txt, 0, list);
+ }
+
+ fsync(q->fd);
+
+ return q;
+}
#include "send_help.h"
#include "send_mails.h"
-void send_help(struct mlmmj_list *list, const char *queuefilename,
+void send_help(struct mlmmj_list *list, struct queuedmail *q,
const char *emailaddr)
{
struct mail_headers mh;
char *fromaddr;
- int queuefd;
xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim,
list->fqdn);
memset(&mh, 0, sizeof(mh));
mh.to = emailaddr;
mh.from = fromaddr;
- queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
{
text *txt;
subs_list_state *normalsls, *digestsls, *nomailsls;
- char *queuefilename;
struct mail_headers mh;
char *fromaddr;
- int fd, queuefd;;
+ int fd;;
+ struct queuedmail *q;
xasprintf(&fromaddr, "%s%sbounces-help@%s", list->name, list->delim, list->fqdn);
rewind_subs_list, get_sub, digestsls);
register_formatted(txt, "nomailsubs",
rewind_subs_list, get_sub, nomailsls);
- queuefilename = prepstdreply(txt, list, "$listowner$", emailaddr, NULL, false);
- MY_ASSERT(queuefilename);
+ q = prepqstdreply(txt, list, "$listowner$", emailaddr, NULL);
+ MY_ASSERT(q);
close_text(txt);
- queuefd = openat(list->queuefd, queuefilename, O_RDONLY);
/* DEPRECATED */
/* Add lists manually if they weren't encountered in the list text */
if (!normalsls->used && !digestsls->used && !nomailsls->used) {
- fd = open(queuefilename, O_WRONLY);
+ fd = openat(list->queuefd, q->name, O_WRONLY);
if(fd < 0) {
log_error(LOG_ARGS, "Could not open sub list mail");
exit(EXIT_FAILURE);
memset(&mh, 0, sizeof(mh));
mh.to = emailaddr;
mh.from = fromaddr;
- if (send_single_mail(list, &mh, queuefd, queuefilename))
+ if (send_single_mail(list, &mh, q))
exit(EXIT_SUCCESS);
exit(EXIT_FAILURE);
}
}
bool
-send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, int mailfd, const char *mailfilename)
+send_single_mail(struct mlmmj_list *list, struct mail_headers *mh, struct queuedmail *q)
{
ssize_t memmailsize;
bool prepmailinmem = true;
if (memmailsize == 0)
memmailsize = MEMORYMAILSIZE;
- if (fstat(mailfd, &st) < 0) {
+ if (fstat(q->fd, &st) < 0) {
log_error(LOG_ARGS, "Could not stat mailfd");
return (false);
}
"MAil is %zu bytes", st.st_size);
}
- mailmap = mmap(0, st.st_size, PROT_READ, MAP_SHARED, mailfd, 0);
+ mailmap = mmap(0, st.st_size, PROT_READ, MAP_SHARED, q->fd, 0);
if (mailmap == MAP_FAILED) {
log_error(LOG_ARGS, "Could not mmap mailfd");
return (false);
sockfd = -1;
/* dump data we want when resending first check
* if it already exists. In that case continue */
- xasprintf(&tmpstr, "%s.mailfrom", mailfilename);
+ xasprintf(&tmpstr, "%s.mailfrom", q->name);
if(stat(tmpstr, &st) == 0) {
free(tmpstr);
goto out;
fsync(tmpfd);
}
close(tmpfd);
- xasprintf(&tmpstr, "%s.reciptto", mailfilename);
+ xasprintf(&tmpstr, "%s.reciptto", q->name);
if(stat(tmpstr, &st) == 0) {
free(tmpstr);
goto out;
}
close(tmpfd);
if(mh->replyto) {
- xasprintf(&tmpstr, "%s.reply-to", mailfilename);
+ xasprintf(&tmpstr, "%s.reply-to", q->name);
if(stat(tmpstr, &st) == 0) {
free(tmpstr);
goto out;
free(hdrs);
free(body);
munmap(mailmap, st.st_size);
- close(mailfd);
free(smtphelo);
/* TODO Archive goes here */
#include <stdlib.h>
#include <errno.h>
+#include "xmalloc.h"
#include "chomp.h"
#include "mlmmj.h"
#include "wrappers.h"
ATF_TC_BODY(open_text, tc)
{
struct mlmmj_list list;
+ char *qname;
init_ml(true);
mlmmj_list_init(&list);
text *txt = open_text(&list, "finish", "sub", "request", "normal", "sub-confirm");
ATF_CHECK(txt != NULL);
register_unformatted(txt, "subaddr", "john@doe.net");
- char *qname = prepstdreply(txt, &list, "$helpaddr$", "john@doe.net", NULL, false);
+ struct queuedmail *q = prepqstdreply(txt, &list, "$helpaddr$", "john@doe.net", NULL);
+ xasprintf(&qname, "%s/queue/%s", list.dir, q->name);
if (!atf_utils_grep_file("^To: john@doe.net", qname) ||
!atf_utils_grep_file("^The email address .*john@doe.net.*", qname) ||
!atf_utils_grep_file("^Subject: .*Welcome_to_test", qname)) {