+ o Deprecate various list text substitutions such as $newsub$, $oldsub$,
+ $moderateaddr$
+ o Add $permitaddr$ and $releaseaddr$ substitutions
+ o Make $subject$, $posteraddr$ and $subaddr$ more widely available
o Fix potential crash when mail to the owner arrives with no From: header
o Add %originalmail% directive and restore backward compatibility of
$originalmail$
DEPRECATED: use %bouncenumbers%
- $confaddr$
+- $confirmaddr$
(available only in confirm-[un]sub-*)
the address to which to send mail to confirm the (un-)subscription in
question
+ NOTE: the short version of this substitution is DEPRECATED
- $control C$
the contents of the control file named C in listdir/control, with its final
(available only in moderate-post-* and gatekeep-sub)
the address to which to send mail to approve the post or subscription in
question
+ DEPRECATED: use $releaseaddr$ or $permitaddr$ instead
- $moderators$
(available only in moderate-post-*, wait-post-*, gatekeep-sub and wait-sub)
the formatted list of moderators to whom the moderation request has been sent
- DEPRECATED: use %moderators% or %gatekeepers%
+ DEPRECATED: use %moderators% or %gatekeepers% instead
- $newsub$
(available only in notify-sub-*-*)
the address that has been subscribed
+ DEPRECATED: use $subaddr$ instead
- $nomailsubaddr$
listname+subscribe-nomail@domain.tld
DEPRECATED: use $list+$unsubscribe-nomail@$domain$ instead
- $oldsub$
- (available only in notify-nsub-*-*)
+ (available only in notify-sub-*-*)
the address that has been unsubscribed
+ DEPRECATED: use $subaddr$ instead
- $originalmail$
the same as %originalmail 100% preceded by a space
DEPRECATED: use %originalmail%
+- $permitaddr$
+ (available only in gatekeep-sub)
+ the address to which to send mail to permit the subscription in question
+
- $posteraddr$
- (available only in deny-post-{access|tocc|subonlypost}, moderate-post-* and
- wait-post-*)
+ (available only in deny-post-{access|tocc|subonlypost|maxmailsize},
+ moderate-post-* and wait-post-*)
the from address of the message that was received as determined by Mlmmj
- $random0$
that are MIME messages with attachments by creating boundaries that are
unlikely to appear in the attached messages
+- $releaseaddr$
+ (available only in moderate-post-*)
+ the address to which to send mail to release the post in question
+
- $subaddr$
- (available only in gatekeep-sub and confirm-[un]sub-*)
+ (available only in gatekeep-sub, confirm-[un]sub-*, finish-[un]sub-*,
+ notify-[un]sub-* and deny-[un]sub-*)
the address requested to be (un-)subscribed
- $subject$
- (available only in deny-post-{access|tocc|subonlypost}, moderate-post-* and
- wait-post-*)
+ (available only in deny-post-{access|tocc|subonlypost|maxmailsize},
+ moderate-post-* and wait-post-*)
the subject line of the message in question
- $text T$
typedef struct text text;
char *substitute(const char *line, const char *listaddr, const char *listdelim,
- size_t datacount, char **data, const char *listdir);
+ const char *listdir, text *txt);
text *open_text_file(const char *listdir, const char *filename);
text *open_text(const char *listdir, const char *purpose, const char *action,
const char *reason, const char *type, const char *compat);
+void register_unformatted(text *txt, const char *token, const char *subst);
+void register_originalmail(text *txt, const char *mailname);
char *get_processed_text_line(text *txt,
- const char *listaddr, const char *listdelim,
- size_t datacount, char **data, const char *listdir,
- const char *mailname);
+ const char *listaddr, const char *listdelim, const char *listdir);
void close_text(text *txt);
-char *prepstdreply(const char *listdir, const char *purpose, const char *action,
- const char *reason, const char *type, const char *compat,
- const char *from, const char *to, const char *replyto,
- size_t tokencount, char **data, const char *mailname);
+char *prepstdreply(text *txt, const char *listdir,
+ const char *from, const char *to, const char *replyto);
#endif /* PREPSTDREPLY_H */
#ifndef SEND_HELP_H
#define SEND_HELP_H
-void send_help(const char *listdir, const char *emailaddr,
- const char *mlmmjsend, const char *purpose, const char *action,
- const char *reason, const char *type, const char *compat);
+void send_help(const char *listdir, const char *queuefilename,
+ const char *emailaddr, const char *mlmmjsend);
#endif
#include "find_email_adr.h"
#include "getlistdelim.h"
#include "strgen.h"
+#include "prepstdreply.h"
#include "send_help.h"
#include "send_list.h"
#include "log_error.h"
unsigned int ctrl;
struct strlist *owners;
int owner_idx;
+ text *txt;
+ char *queuefilename;
/* A closed list doesn't allow subscribtion and unsubscription */
closedlist = statctrl(listdir, "closedlist");
}
if (statctrl(listdir, "nodigestsub")) {
errno = 0;
- log_error(LOG_ARGS, "A subcribe-digest request was"
+ log_error(LOG_ARGS, "A subscribe-digest request was"
" denied");
- send_help(listdir, fromemails->emaillist[0],
- mlmmjsend, "deny", "sub", "disabled", "digest", "sub-deny-digest");
+ txt = open_text(listdir, "deny", "sub", "disabled",
+ "digest", "sub-deny-digest");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr",
+ fromemails->emaillist[0]);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$",
+ fromemails->emaillist[0], NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
+ send_help(listdir, queuefilename,
+ fromemails->emaillist[0], mlmmjsend);
return -1;
}
log_oper(listdir, OPLOGFNAME, "mlmmj-sub: request for digest"
}
if (statctrl(listdir, "nonomailsub")) {
errno = 0;
- log_error(LOG_ARGS, "A subcribe-nomail request was"
+ log_error(LOG_ARGS, "A subscribe-nomail request was"
" denied");
- send_help(listdir, fromemails->emaillist[0],
- mlmmjsend, "deny", "sub", "disabled", "nomail", "sub-deny-nomail");
+ txt = open_text(listdir, "deny", "sub", "disabled",
+ "nomail", "sub-deny-nomail");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr",
+ fromemails->emaillist[0]);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$",
+ fromemails->emaillist[0], NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
+ send_help(listdir, queuefilename,
+ fromemails->emaillist[0], mlmmjsend);
return -1;
}
log_oper(listdir, OPLOGFNAME, "mlmmj-sub: request for nomail"
}
log_oper(listdir, OPLOGFNAME, "%s requested help",
fromemails->emaillist[0]);
- send_help(listdir, fromemails->emaillist[0], mlmmjsend,
- "help", NULL, NULL, NULL, "listhelp");
+ txt = open_text(listdir, "help", NULL, NULL, NULL, "listhelp");
+ MY_ASSERT(txt);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", fromemails->emaillist[0], NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
+ send_help(listdir, queuefilename,
+ fromemails->emaillist[0], mlmmjsend);
break;
/* listname+faq@domain.tld */
}
log_oper(listdir, OPLOGFNAME, "%s requested faq",
fromemails->emaillist[0]);
- send_help(listdir, fromemails->emaillist[0], mlmmjsend,
- "faq", NULL, NULL, NULL, "listfaq");
+ txt = open_text(listdir, "faq", NULL, NULL, NULL, "listfaq");
+ MY_ASSERT(txt);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", fromemails->emaillist[0], NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
+ send_help(listdir, queuefilename,
+ fromemails->emaillist[0], mlmmjsend);
break;
/* listname+get-INDEX@domain.tld */
void do_probe(const char *listdir, const char *mlmmjsend, const char *addr)
{
+ text *txt;
char *myaddr, *from, *a, *indexstr, *queuefilename, *listaddr;
char *listfqdn, *listname, *probefile, *listdelim=getlistdelim(listdir);
- char *maildata[] = { "bouncenumbers", NULL };
int fd;
time_t t;
exit(EXIT_FAILURE);
}
- maildata[1] = indexstr;
- queuefilename = prepstdreply(listdir,
- "probe", NULL, NULL, NULL, "bounce-probe",
- "$listowner$", myaddr, NULL, 1, maildata, NULL);
- MY_ASSERT(queuefilename);
+ txt = open_text(listdir, "probe", NULL, NULL, NULL, "bounce-probe");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "bouncenumbers", indexstr);
myfree(indexstr);
+ queuefilename = prepstdreply(txt, listdir, "$listowner$", myaddr, NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
probefile = concatstr(4, listdir, "/bounce/", addr, "-probe");
MY_ASSERT(probefile);
};
-void newmoderated(const char *listdir, const char *mailfilename,
+static void newmoderated(const char *listdir, const char *mailfilename,
const char *mlmmjsend, const char *efromsender,
- size_t tokencount, char **data, enum modreason modreason)
+ const char *subject, const char *posteraddr,
+ enum modreason modreason)
{
- size_t i;
char *from, *listfqdn, *listname, *moderators = NULL;
char *buf, *replyto, *listaddr = getlistaddr(listdir), *listdelim;
+ text *txt;
char *queuefilename = NULL, *moderatorsfilename, *efromismod = NULL;
char *mailbasename = mybasename(mailfilename), *tmp, *to;
int moderatorsfd, foundaddr = 0, notifymod = 0, status;
- char *maildata[10] = { "moderateaddr", NULL, "moderators", NULL };
pid_t childpid, pid;
#if 0
printf("mailfilename = [%s], mailbasename = [%s]\n", mailfilename,
listfqdn = genlistfqdn(listaddr);
listname = genlistname(listaddr);
- MY_ASSERT(tokencount<=3)
- for (i=0; i<tokencount; i++) {
- maildata[4+2*i] = data[2*i];
- maildata[5+2*i] = data[1+2*i];
- }
- tokencount += 2;
-
moderatorsfilename = concatstr(2, listdir, "/control/moderators");
if((moderatorsfd = open(moderatorsfilename, O_RDONLY)) < 0) {
log_error(LOG_ARGS, "Could not open '%s'", moderatorsfilename);
replyto = concatstr(6, listname, listdelim, "moderate-", mailbasename,
"@", listfqdn);
- maildata[1] = replyto;
- if(efromismod) {
- myfree(moderators);
- maildata[3] = efromismod;
- } else
- maildata[3] = moderators;
-
from = concatstr(4, listname, listdelim, "owner@", listfqdn);
to = concatstr(3, listname, "-moderators@", listfqdn); /* FIXME JFA: Should this be converted? Why, why not? */
myfree(listname);
myfree(listfqdn);
- queuefilename = prepstdreply(listdir,
- "moderate", "post", modreason_strs[modreason], NULL,
- "moderation", "$listowner$", to, replyto,
- tokencount, maildata, mailfilename);
+ txt = open_text(listdir, "moderate", "post",
+ modreason_strs[modreason], NULL, "moderation");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subject", subject);
+ register_unformatted(txt, "posteraddr", posteraddr);
+ register_unformatted(txt, "moderateaddr", replyto); /* DEPRECATED */
+ register_unformatted(txt, "releaseaddr", replyto);
+ if(efromismod) register_unformatted(txt, "moderators", efromismod);
+ else register_unformatted(txt, "moderators", moderators);
+ register_originalmail(txt, mailfilename);
+ queuefilename = prepstdreply(txt, listdir, "$listowner$", to, replyto);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
/* we might need to exec more than one mlmmj-send */
/* send mail to poster that the list is moderated */
- queuefilename = prepstdreply(listdir,
- "wait", "post", modreason_strs[modreason], NULL,
- "moderation-poster", "$listowner$", efromsender,
- NULL, tokencount-1, maildata+2, mailfilename);
+ txt = open_text(listdir, "wait", "post",
+ modreason_strs[modreason], NULL, "moderation-poster");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subject", subject);
+ register_unformatted(txt, "posteraddr", posteraddr);
+ if(efromismod) register_unformatted(txt, "moderators", efromismod);
+ else register_unformatted(txt, "moderators", moderators);
+ register_originalmail(txt, mailfilename);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", efromsender, NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
char *mlmmjsend, *mlmmjsub, *mlmmjunsub, *mlmmjbounce;
char *bindir, *subjectprefix, *discardname, *listaddr, *listdelim;
char *listfqdn, *listname, *fromaddr;
+ text *txt;
char *queuefilename, *recipextra = NULL, *owner = NULL;
char *maxmailsizestr;
- char *maildata[6] = { "subject", NULL,
- "posteraddr", NULL, "maxmailsize", NULL };
+ char *subject = NULL, *posteraddr = NULL;
char *envstr, *efrom;
struct stat st;
uid_t uid;
/* TODO: free emailstructs */
exit(EXIT_SUCCESS);
}
- maildata[3] = fromemails.emaillist[0];
-
- if (fromemails.emailcount)
- maildata[3] = fromemails.emaillist[0];
+ posteraddr = fromemails.emaillist[0];
/* To: addresses */
for(i = 0; i < readhdrs[1].valuecount; i++) {
/* Subject: */
if (readhdrs[5].valuecount)
- maildata[1] = unistr_header_to_utf8(readhdrs[5].values[0]);
- if (!maildata[1])
- maildata[1] = mystrdup("");
+ subject = unistr_header_to_utf8(readhdrs[5].values[0]);
+ if (!subject) subject = mystrdup("");
/* envelope from */
if((envstr = getenv("SENDER")) != NULL) {
listfqdn = genlistfqdn(listaddr);
fromaddr = concatstr(4, listname, listdelim,
"bounces-help@", listfqdn);
- maildata[5] = maxmailsizestr;
- queuefilename = prepstdreply(listdir,
- "deny", "post", "maxmailsize", NULL,
- "maxmailsize", "$listowner$",
- fromemails.emaillist[0],
- NULL, 1, maildata+4, donemailname);
- MY_ASSERT(queuefilename)
+ txt = open_text(listdir, "deny", "post",
+ "maxmailsize", NULL, "maxmailsize");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subject", subject);
+ register_unformatted(txt, "posteraddr", posteraddr);
+ register_unformatted(txt, "maxmailsize", maxmailsizestr);
+ register_originalmail(txt, donemailname);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", posteraddr, NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
myfree(listdelim);
myfree(listname);
myfree(listfqdn);
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
"-L", listdir,
- "-T", fromemails.emaillist[0],
+ "-T", posteraddr,
"-F", fromaddr,
"-m", queuefilename, (char *)NULL);
/* Don't send a mail about denial to the list, but silently
* discard and exit. Also don't in case of it being turned off
*/
- if ((strcasecmp(listaddr, fromemails.emaillist[0]) == 0) ||
+ if ((strcasecmp(listaddr, posteraddr) == 0) ||
notoccdenymails) {
log_error(LOG_ARGS, "Discarding %s because list"
" address was not in To: or Cc:,"
listfqdn = genlistfqdn(listaddr);
fromaddr = concatstr(4, listname, listdelim, "bounces-help@",
listfqdn);
- queuefilename = prepstdreply(listdir,
- "deny", "post", "notintocc", NULL, "notintocc",
- "$listowner$", fromemails.emaillist[0], NULL,
- 2, maildata, donemailname);
+ txt = open_text(listdir, "deny", "post",
+ "notintocc", NULL, "notintocc");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subject", subject);
+ register_unformatted(txt, "posteraddr", posteraddr);
+ register_originalmail(txt, donemailname);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", posteraddr, NULL);
MY_ASSERT(queuefilename)
+ close_text(txt);
myfree(listdelim);
myfree(listname);
myfree(listfqdn);
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
"-L", listdir,
- "-T", fromemails.emaillist[0],
+ "-T", posteraddr,
"-F", fromaddr,
"-m", queuefilename, (char *)NULL);
if(subonlypost) {
/* Don't send a mail about denial to the list, but silently
* discard and exit. */
- if (strcasecmp(listaddr, fromemails.emaillist[0]) == 0) {
+ if (strcasecmp(listaddr, posteraddr) == 0) {
log_error(LOG_ARGS, "Discarding %s because"
" subonlypost was set and From: was"
" the list address",
myfree(donemailname);
exit(EXIT_SUCCESS);
}
- if(is_subbed(listdir, fromemails.emaillist[0]) != 0) {
+ if(is_subbed(listdir, posteraddr) != 0) {
modnonsubposts = statctrl(listdir,
"modnonsubposts");
if(modnonsubposts) {
listfqdn = genlistfqdn(listaddr);
fromaddr = concatstr(4, listname, listdelim,
"bounces-help@", listfqdn);
- queuefilename = prepstdreply(listdir,
- "deny", "post", "subonlypost", NULL,
- "subonlypost", "$listowner$",
- fromemails.emaillist[0], NULL,
- 2, maildata, donemailname);
+ txt = open_text(listdir, "deny", "post",
+ "subonlypost", NULL, "subonlypost");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subject", subject);
+ register_unformatted(txt, "posteraddr", posteraddr);
+ register_originalmail(txt, donemailname);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", posteraddr, NULL);
MY_ASSERT(queuefilename)
+ close_text(txt);
myfree(listaddr);
myfree(listdelim);
myfree(listname);
myfree(donemailname);
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
- "-T", fromemails.emaillist[0],
+ "-T", posteraddr,
"-F", fromaddr,
"-m", queuefilename, (char *)NULL);
/* Don't send a mail about denial to the list, but silently
* discard and exit. Also do this in case it's turned off */
accret = do_access(access_rules, &allheaders,
- fromemails.emaillist[0], listdir);
+ posteraddr, listdir);
if (accret == DENY) {
- if ((strcasecmp(listaddr, fromemails.emaillist[0]) ==
- 0) || noaccessdenymails) {
+ if ((strcasecmp(listaddr, posteraddr) == 0) ||
+ noaccessdenymails) {
log_error(LOG_ARGS, "Discarding %s because"
" it was denied by an access"
" rule, and From: was the list"
listfqdn = genlistfqdn(listaddr);
fromaddr = concatstr(4, listname, listdelim,
"bounces-help@", listfqdn);
- queuefilename = prepstdreply(listdir,
- "deny", "post", "access", NULL,
- "access", "$listowner$",
- fromemails.emaillist[0], NULL,
- 2, maildata, donemailname);
+ txt = open_text(listdir, "deny", "post",
+ "access", NULL, "access");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subject", subject);
+ register_unformatted(txt, "posteraddr", posteraddr);
+ register_originalmail(txt, donemailname);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", posteraddr, NULL);
MY_ASSERT(queuefilename)
+ close_text(txt);
myfree(listaddr);
myfree(listdelim);
myfree(listname);
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
"-L", listdir,
- "-T", fromemails.emaillist[0],
+ "-T", posteraddr,
"-F", fromaddr,
"-m", queuefilename, (char *)NULL);
exit(EXIT_FAILURE);
}
myfree(omitfilename);
- if(writen(omitfd, fromemails.emaillist[0],
- strlen(fromemails.emaillist[0])) < 0) {
+ if(writen(omitfd, posteraddr, strlen(posteraddr)) < 0) {
log_error(LOG_ARGS,
"could not write omit file");
myfree(mqueuename);
close(omitfd);
}
newmoderated(listdir, mqueuename,
- mlmmjsend, efrom, 2, maildata, modreason);
+ mlmmjsend, efrom, subject, posteraddr,
+ modreason);
return EXIT_SUCCESS;
}
if (notmetoo)
execlp(mlmmjsend, mlmmjsend,
"-L", listdir,
- "-o", fromemails.emaillist[0],
+ "-o", posteraddr,
"-m", donemailname, (char *)NULL);
else
execlp(mlmmjsend, mlmmjsend,
const char *mlmmjsend, enum subtype typesub)
{
int i, fd, status, nosubmodmails = 0;
+ text *txt;
char *a = NULL, *queuefilename, *from, *listname, *listfqdn, *str;
char *modfilename, *randomstr, *mods, *to, *replyto, *moderators = NULL;
char *modfilebase;
struct strlist *submods;
pid_t childpid, pid;
- char *maildata[6] = { "subaddr", NULL, "moderateaddr", NULL,
- "moderators", NULL };
/* generate the file in moderation/ */
switch(typesub) {
myfree(str);
}
- maildata[1] = mystrdup(subaddr);
- maildata[3] = replyto;
- maildata[5] = moderators;
-
- queuefilename = prepstdreply(listdir,
- "gatekeep", "sub", NULL, NULL, "submod-moderator",
- "$listowner$", to, replyto, 3, maildata, NULL);
-
- myfree(maildata[1]);
+ txt = open_text(listdir,
+ "gatekeep", "sub", NULL, NULL, "submod-moderator");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ register_unformatted(txt, "moderateaddr", replyto); /* DEPRECATED */
+ register_unformatted(txt, "permitaddr", replyto);
+ register_unformatted(txt, "moderators", moderators);
+ queuefilename = prepstdreply(txt, listdir, "$listowner$", to, replyto);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
/* we might need to exec more than one mlmmj-send */
myfree(to);
myfree(replyto);
- myfree(moderators);
/* send mail to requester that the list is submod'ed */
from = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
- queuefilename = prepstdreply(listdir,
- "wait", "sub", NULL, NULL, "submod-requester",
- "$listowner$", subaddr, NULL, 0, NULL, NULL);
+
+ txt = open_text(listdir,
+ "wait", "sub", NULL, NULL, "submod-requester");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ register_unformatted(txt, "moderators", moderators);
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", subaddr, NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
myfree(listname);
myfree(listfqdn);
+ myfree(moderators);
execl(mlmmjsend, mlmmjsend,
"-l", "1",
"-L", listdir,
const char *listdelim, const char *subaddr,
const char *mlmmjsend, enum subtype typesub, enum subreason reasonsub)
{
+ text *txt;
char *queuefilename, *fromaddr, *listname, *listfqdn, *listtext;
listname = genlistname(listaddr);
break;
}
- queuefilename = prepstdreply(listdir,
- "finish", "sub",
+ txt = open_text(listdir, "finish", "sub",
subreason_strs[reasonsub], subtype_strs[typesub],
- listtext, "$helpaddr$", subaddr, NULL,
- 0, NULL, NULL);
- MY_ASSERT(queuefilename);
+ listtext);
myfree(listtext);
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ queuefilename = prepstdreply(txt, listdir,
+ "$helpaddr$", subaddr, NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
const char *listdelim, const char *subaddr,
const char *mlmmjsend, enum subtype typesub, enum subreason reasonsub)
{
- char *maildata[2] = { "newsub", NULL };
char *listfqdn, *listname, *fromaddr, *tostr;
+ text *txt;
char *queuefilename = NULL, *listtext = NULL;
listname = genlistname(listaddr);
listfqdn = genlistfqdn(listaddr);
- maildata[1] = mystrdup(subaddr);
-
fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
tostr = concatstr(4, listname, listdelim, "owner@", listfqdn);
break;
}
- queuefilename = prepstdreply(listdir,
- "notify", "sub",
+ txt = open_text(listdir, "notify", "sub",
subreason_strs[reasonsub], subtype_strs[typesub],
- listtext, "$listowner$", "$listowner$", NULL,
- 1, maildata, NULL);
- MY_ASSERT(queuefilename)
+ listtext);
myfree(listtext);
- myfree(maildata[1]);
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ register_unformatted(txt, "newsub", subaddr); /* DEPRECATED */
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", "$listowner$", NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
+
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
"-L", listdir,
{
int subconffd;
char *confirmaddr, *listname, *listfqdn, *confirmfilename = NULL;
+ text *txt;
char *listtext, *queuefilename = NULL, *fromaddr;
char *randomstr = NULL, *tmpstr;
- char *maildata[4] = { "subaddr", NULL, "confaddr", NULL };
listname = genlistname(listaddr);
listfqdn = genlistfqdn(listaddr);
myfree(randomstr);
myfree(tmpstr);
- maildata[1] = mystrdup(subaddr);
- maildata[3] = mystrdup(confirmaddr);
-
- queuefilename = prepstdreply(listdir,
- "confirm", "sub",
+ txt = open_text(listdir, "confirm", "sub",
subreason_strs[reasonsub], subtype_strs[typesub],
- listtext, "$helpaddr$", subaddr, confirmaddr,
- 2, maildata, NULL);
-
- myfree(maildata[1]);
- myfree(maildata[3]);
+ listtext);
+ myfree(listtext);
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ register_unformatted(txt, "confaddr", confirmaddr); /* DEPRECATED */
+ register_unformatted(txt, "confirmaddr", confirmaddr);
+ queuefilename = prepstdreply(txt, listdir,
+ "$helpaddr$", subaddr, confirmaddr);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
myfree(listname);
myfree(listfqdn);
void generate_subscribed(const char *listdir, const char *subaddr,
const char *mlmmjsend)
{
+ text *txt;
char *queuefilename, *fromaddr, *listname, *listfqdn, *listaddr;
char *listdelim = getlistdelim(listdir);
fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
myfree(listdelim);
- queuefilename = prepstdreply(listdir,
- "deny", "sub", "subbed", NULL, "sub-subscribed",
- "$helpaddr$", subaddr, NULL, 0, NULL, NULL);
+ txt = open_text(listdir,
+ "deny", "sub", "subbed", NULL, "sub-subscribed");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ queuefilename = prepstdreply(txt, listdir,
+ "$helpaddr$", subaddr, NULL);
MY_ASSERT(queuefilename);
+ close_text(txt);
myfree(listaddr);
myfree(listname);
const char *mlmmjsend,
enum subtype typesub, enum subreason reasonsub)
{
+ text *txt;
char *queuefilename, *fromaddr, *listname, *listfqdn, *listtext;
listname = genlistname(listaddr);
break;
}
- queuefilename = prepstdreply(listdir,
- "finish", "unsub",
+ txt = open_text(listdir, "finish", "unsub",
subreason_strs[reasonsub], subtype_strs[typesub],
- listtext, "$helpaddr$", subaddr, NULL, 0, NULL, NULL);
- MY_ASSERT(queuefilename);
+ listtext);
myfree(listtext);
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ queuefilename = prepstdreply(txt, listdir,
+ "$helpaddr$", subaddr, NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
const char *mlmmjsend,
enum subtype typesub, enum subreason reasonsub)
{
- char *maildata[4] = { "oldsub", NULL };
char *listfqdn, *listname, *fromaddr, *tostr;
+ text *txt;
char *queuefilename = NULL, *listtext;
listname = genlistname(listaddr);
listfqdn = genlistfqdn(listaddr);
- maildata[1] = mystrdup(subaddr);
-
fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
tostr = concatstr(4, listname, listdelim, "owner@", listfqdn);
break;
}
- queuefilename = prepstdreply(listdir,
- "notify", "unsub",
+ txt = open_text(listdir, "notify", "unsub",
subreason_strs[reasonsub], subtype_strs[typesub],
- listtext, "$listowner$", "$listowner$", NULL,
- 1, maildata, NULL);
- MY_ASSERT(queuefilename);
+ listtext);
myfree(listtext);
- myfree(maildata[1]);
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ register_unformatted(txt, "oldsub", subaddr); /* DEPRECATED */
+ queuefilename = prepstdreply(txt, listdir,
+ "$listowner$", "$listowner$", NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
enum subtype typesub, enum subreason reasonsub)
{
char *confirmaddr, *listname, *listfqdn, *tmpstr;
+ text *txt;
char *queuefilename, *fromaddr;
char *randomstr = NULL, *confirmfilename = NULL, *listtext;
- char *maildata[4] = { "subaddr", NULL, "confaddr", NULL };
int subconffd;
listname = genlistname(listaddr);
myfree(randomstr);
myfree(tmpstr);
- maildata[1] = mystrdup(subaddr);
- maildata[3] = mystrdup(confirmaddr);
-
- queuefilename = prepstdreply(listdir,
- "confirm", "unsub",
+ txt = open_text(listdir, "confirm", "unsub",
subreason_strs[reasonsub], subtype_strs[typesub],
- listtext, "$helpaddr$", subaddr, confirmaddr,
- 2, maildata, NULL);
-
- myfree(maildata[1]);
- myfree(maildata[3]);
+ listtext);
+ myfree(listtext);
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ register_unformatted(txt, "confaddr", confirmaddr); /* DEPRECATED */
+ register_unformatted(txt, "confirmaddr", confirmaddr);
+ queuefilename = prepstdreply(txt, listdir,
+ "$helpaddr$", subaddr, confirmaddr);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
myfree(listname);
myfree(listfqdn);
void generate_notsubscribed(const char *listdir, const char *subaddr,
const char *mlmmjsend)
{
+ text *txt;
char *queuefilename, *fromaddr, *listname, *listfqdn, *listaddr;
char *listdelim = getlistdelim(listdir);
fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
myfree(listdelim);
- queuefilename = prepstdreply(listdir,
+ txt = open_text(listdir,
"deny", "unsub", "unsubbed", NULL,
- "unsub-notsubscribed", "$helpaddr$", subaddr, NULL,
- 0, NULL, NULL);
+ "unsub-notsubscribed");
+ MY_ASSERT(txt);
+ register_unformatted(txt, "subaddr", subaddr);
+ queuefilename = prepstdreply(txt, listdir,
+ "$helpaddr$", subaddr, NULL);
MY_ASSERT(queuefilename);
+ close_text(txt);
myfree(listaddr);
myfree(listname);
};
+struct substitution;
+typedef struct substitution substitution;
+struct substitution {
+ char *token;
+ char *subst;
+ substitution *next;
+};
+
+
struct text {
source *src;
+ substitution *substs;
+ char *mailname;
};
static void substitute_one(char **line_p, char **pos_p, const char *listaddr,
- const char *listdelim, size_t datacount, char **data,
- const char *listdir)
+ const char *listdelim, const char *listdir, text *txt)
{
char *line = *line_p;
char *pos = *pos_p;
char *endpos;
char *fqdn, *listname;
char *value = NULL;
- size_t i;
+ substitution *subst;
endpos = strchr(token, '$');
if (endpos == NULL) {
} else if(strcmp(token, "originalmail") == 0) {
/* DEPRECATED: use %originalmail% instead */
value = mystrdup(" %originalmail 100%");
- } else if(data) {
- for(i = 0; i < datacount; i++) {
- if(strcmp(token, data[i*2]) == 0) {
- value = mystrdup(data[(i*2)+1]);
+ } else {
+ subst = txt->substs;
+ while (subst != NULL) {
+ if(strcmp(token, subst->token) == 0) {
+ value = mystrdup(subst->subst);
break;
}
+ subst = subst->next;
}
}
char *substitute(const char *line, const char *listaddr, const char *listdelim,
- size_t datacount, char **data, const char *listdir)
+ const char *listdir, text *txt)
{
char *new;
char *pos;
while (*pos != '\0') {
if (*pos == '$') {
substitute_one(&new, &pos,
- listaddr, listdelim,
- datacount, data, listdir);
+ listaddr, listdelim, listdir, txt);
/* The function sets up for the next character
* to process, so continue straight away. */
continue;
txt->src->suffix = NULL;
txt->src->transparent = 0;
txt->src->limit = -1;
+ txt->substs = NULL;
+ txt->mailname = NULL;
tmp = concatstr(3, listdir, "/text/", filename);
txt->src->fd = open(tmp, O_RDONLY);
}
+void register_unformatted(text *txt, const char *token, const char *replacement)
+{
+ substitution * subst = mymalloc(sizeof(substitution));
+ subst->token = mystrdup(token);
+ subst->subst = mystrdup(replacement);
+ subst->next = txt->substs;
+ txt->substs = subst;
+}
+
+
+void register_originalmail(text *txt, const char *mailname)
+{
+ txt->mailname = mystrdup(mailname);
+}
+
+
static void begin_new_source_file(text *txt, char **line_p, char **pos_p,
const char *filename) {
char *line = *line_p;
static void handle_directive(text *txt, char **line_p, char **pos_p,
- const char *listdir, const char *mailname) {
+ const char *listdir) {
char *line = *line_p;
char *pos = *pos_p;
char *token = pos + 1;
myfree(filename);
return;
}
- } else if(strncmp(token, "originalmail", 12) == 0 && mailname != NULL) {
+ } else if(strncmp(token, "originalmail", 12) == 0 &&
+ txt->mailname != NULL) {
token += 12;
limit = 0;
if (*token == '\0') {
if (token != NULL) limit = atol(token);
}
if (limit != 0) {
- begin_new_source_file(txt, line_p, pos_p, mailname);
+ begin_new_source_file(txt, line_p, pos_p,
+ txt->mailname);
txt->src->transparent = 1;
if (limit == -1) txt->src->limit = -1;
else txt->src->limit = limit - 1;
char *get_processed_text_line(text *txt,
const char *listaddr, const char *listdelim,
- size_t datacount, char **data, const char *listdir,
- const char *mailname)
+ const char *listdir)
{
char *line = NULL;
char *pos;
* transparently */
} else if (*pos == '$') {
substitute_one(&line, &pos,
- listaddr, listdelim,
- datacount, data, listdir);
+ listaddr, listdelim, listdir, txt);
/* The function sets up for the next character
* to process, so continue straight away. */
continue;
} else if (*pos == '%') {
- handle_directive(txt, &line, &pos, listdir, mailname);
+ handle_directive(txt, &line, &pos, listdir);
/* The function sets up for the next character
* to process, so continue straight away. */
continue;
void close_text(text *txt) {
source *tmp;
+ substitution *subst;
while (txt->src != NULL) {
close(txt->src->fd);
tmp = txt->src;
txt->src = txt->src->prev;
myfree(tmp);
}
+ while (txt->substs != NULL) {
+ subst = txt->substs;
+ myfree(subst->token);
+ myfree(subst->subst);
+ txt->substs = txt->substs->next;
+ myfree(subst);
+ }
+ if (txt->mailname != NULL) myfree(txt->mailname);
+ myfree(txt);
}
-char *prepstdreply(const char *listdir, const char *purpose, const char *action,
- const char *reason, const char *type, const char *compat,
- const char *from, const char *to, const char *replyto,
- size_t tokencount, char **data, const char *mailname)
+char *prepstdreply(text *txt, const char *listdir,
+ const char *from, const char *to, const char *replyto)
{
size_t len, i;
int outfd;
- text *txt;
char *listaddr, *listdelim, *tmp, *retstr = NULL;
char *listfqdn, *line;
char *str;
- char **moredata;
char *headers[10] = { NULL }; /* relies on NULL to flag end */
- txt = open_text(listdir, purpose, action, reason, type, compat);
- if (txt == NULL) return NULL;
-
listaddr = getlistaddr(listdir);
listdelim = getlistdelim(listdir);
listfqdn = genlistfqdn(listaddr);
return NULL;
}
- moredata = mymalloc(2*(tokencount+6) * sizeof(char *));
- for (i=0; i<2*tokencount; i++) {
- moredata[i] = data[i];
- }
for (i=0; i<6; i++) {
- moredata[2*(tokencount+i)] = mystrdup("randomN");
- moredata[2*(tokencount+i)][6] = '0' + i;
- moredata[2*(tokencount+i)+1] = random_str();
+ tmp = mystrdup("randomN");
+ tmp[6] = '0' + i;
+ str = random_str();
+ register_unformatted(txt, tmp, str);
+ myfree(tmp);
+ myfree(str);
}
- tokencount += 6;
- tmp = substitute(from, listaddr, listdelim,
- tokencount, moredata, listdir);
+ tmp = substitute(from, listaddr, listdelim, listdir, txt);
headers[0] = concatstr(2, "From: ", tmp);
myfree(tmp);
- tmp = substitute(to, listaddr, listdelim,
- tokencount, moredata, listdir);
+ tmp = substitute(to, listaddr, listdelim, listdir, txt);
headers[1] = concatstr(2, "To: ", tmp);
myfree(tmp);
headers[2] = genmsgid(listfqdn);
headers[7] = mystrdup("Content-Transfer-Encoding: 8bit");
if(replyto) {
- tmp = substitute(replyto, listaddr, listdelim,
- tokencount, moredata, listdir);
+ tmp = substitute(replyto, listaddr, listdelim, listdir, txt);
headers[8] = concatstr(2, "Reply-To: ", tmp);
myfree(tmp);
}
for(;;) {
line = get_processed_text_line(txt, listaddr, listdelim,
- tokencount, moredata, listdir, NULL);
+ listdir);
if (!line) {
log_error(LOG_ARGS, "No body in listtext");
break;
if (line == NULL) {
line = get_processed_text_line(txt, listaddr, listdelim,
- tokencount, moredata, listdir, mailname);
+ listdir);
}
while(line) {
len = strlen(line);
}
myfree(line);
line = get_processed_text_line(txt, listaddr, listdelim,
- tokencount, moredata, listdir, mailname);
+ listdir);
}
fsync(outfd);
myfree(listdelim);
myfree(listfqdn);
- for (i=tokencount-6; i<tokencount; i++) {
- myfree(moredata[2*i]);
- myfree(moredata[2*i+1]);
- }
- myfree(moredata);
-
- close_text(txt);
- myfree(txt);
-
return retstr;
}
int i, fd, archivefd, status, hdrfd;
size_t len;
text * txt;
- char buf[45];
+ char buf[100];
char *tmp, *queuename = NULL, *archivename, *subject = NULL, *line = NULL;
char *boundary, *listaddr, *listdelim, *listname, *listfqdn;
- char *subst_data[10];
pid_t childpid, pid;
if (addr) {
txt = open_text_file(listdir, "digest");
if (txt == NULL) {
log_error(LOG_ARGS, "Could not open listtext 'digest'");
+ goto fallback_subject;
}
- subst_data[0] = "digestfirst";
snprintf(buf, sizeof(buf), "%d", firstindex);
- subst_data[1] = mystrdup(buf);
+ register_unformatted(txt, "digestfirst", buf);
- subst_data[2] = "digestlast";
snprintf(buf, sizeof(buf), "%d", lastindex);
- subst_data[3] = mystrdup(buf);
+ register_unformatted(txt, "digestlast", buf);
- subst_data[4] = "digestinterval";
if (lastindex == firstindex) {
snprintf(buf, sizeof(buf), "%d", firstindex);
} else {
snprintf(buf, sizeof(buf), "%d-%d", firstindex, lastindex);
}
- subst_data[5] = mystrdup(buf);
+ register_unformatted(txt, "digestinterval", buf);
- subst_data[6] = "digestissue";
snprintf(buf, sizeof(buf), "%d", issue);
- subst_data[7] = mystrdup(buf);
+ register_unformatted(txt, "digestissue", buf);
- subst_data[8] = "digestthreads";
- subst_data[9] = thread_list(listdir, firstindex, lastindex);
+ tmp = thread_list(listdir, firstindex, lastindex);
+ register_unformatted(txt, "digestthreads", tmp);
- if (txt == NULL) goto fallback_subject;
-
- line = get_processed_text_line(txt, listaddr, listdelim,
- 5, subst_data, listdir, NULL);
+ line = get_processed_text_line(txt, listaddr, listdelim, listdir);
if (line == NULL) {
log_error(LOG_ARGS, "No content in digest listtext");
/* Skip the empty line after the subject */
line = get_processed_text_line(txt, listaddr, listdelim,
- 5, subst_data, listdir, NULL);
+ listdir);
if (line == NULL || *line != '\0') {
log_error(LOG_ARGS, "Too many headers "
"in digest listtext");
fallback_subject:
if (subject == NULL) {
- tmp = substitute("Digest of $listaddr$ issue $digestissue$"
- " ($digestinterval$)", listaddr, listdelim,
- 5, subst_data, listdir);
- subject = unistr_utf8_to_header(tmp);
+ if (lastindex == firstindex) {
+ snprintf(buf, sizeof(buf), "%d", firstindex);
+ } else {
+ snprintf(buf, sizeof(buf), "%d-%d", firstindex, lastindex);
+ }
+ tmp = mystrdup(buf);
+ snprintf(buf, sizeof(buf), "Digest of %s issue %d (%s)",
+ listaddr, issue, tmp);
+ subject = unistr_utf8_to_header(buf);
myfree(tmp);
}
myfree(listaddr);
myfree(listname);
myfree(listdelim);
- myfree(subst_data[1]);
- myfree(subst_data[3]);
- myfree(subst_data[5]);
- myfree(subst_data[7]);
- myfree(subst_data[9]);
if (txt != NULL) {
close_text(txt);
myfree(line);
myfree(listaddr);
myfree(listname);
myfree(listdelim);
- myfree(subst_data[1]);
- myfree(subst_data[3]);
- myfree(subst_data[5]);
- myfree(subst_data[7]);
- myfree(subst_data[9]);
if (txt != NULL) {
close_text(txt);
myfree(line);
for (;;) {
line = get_processed_text_line(txt, listaddr, listdelim,
- 5, subst_data, listdir, NULL);
+ listdir);
if (line == NULL) break;
len = strlen(line);
line[len] = '\n';
if (line != NULL) myfree(line);
myfree(listaddr);
myfree(listdelim);
- myfree(subst_data[1]);
- myfree(subst_data[3]);
- myfree(subst_data[5]);
- myfree(subst_data[7]);
- myfree(subst_data[9]);
for (i=firstindex; i<=lastindex; i++) {
snprintf(buf, sizeof(buf), "%d", i);
#include "prepstdreply.h"
#include "memory.h"
-void send_help(const char *listdir, const char *emailaddr,
- const char *mlmmjsend, const char *purpose, const char *action,
- const char *reason, const char *type, const char *compat)
+void send_help(const char *listdir, const char *queuefilename,
+ const char *emailaddr, const char *mlmmjsend)
{
- char *queuefilename, *listaddr, *listdelim, *listname, *listfqdn;
+ char *listaddr, *listdelim, *listname, *listfqdn;
char *fromaddr;
listaddr = getlistaddr(listdir);
listfqdn = genlistfqdn(listaddr);
fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
- myfree(listdelim);
- queuefilename = prepstdreply(listdir,
- purpose, action, reason, type, compat,
- "$listowner$", emailaddr, NULL, 0, NULL, NULL);
- if(queuefilename == NULL) {
- if (action == NULL) action = "";
- if (reason == NULL) reason = "";
- if (type == NULL) type = "";
- log_error(LOG_ARGS, "Could not prepare %s-%s-%s-%s mail",
- purpose, action, reason, type);
- exit(EXIT_FAILURE);
- }
-
- myfree(listaddr);
myfree(listname);
+ myfree(listdelim);
myfree(listfqdn);
+ myfree(listaddr);
execlp(mlmmjsend, mlmmjsend,
"-l", "1",
void send_list(const char *listdir, const char *emailaddr,
const char *mlmmjsend)
{
+ text *txt;
char *queuefilename, *listaddr, *listdelim, *listname, *listfqdn;
char *fromaddr, *subdir, *nomaildir, *digestdir;
int fd;
fromaddr = concatstr(4, listname, listdelim, "bounces-help@", listfqdn);
myfree(listdelim);
- queuefilename = prepstdreply(listdir,
- "list", NULL, NULL, subtype_strs[SUB_ALL],
- "listsubs", "$listowner$", emailaddr, NULL,
- 0, NULL, NULL);
- if(queuefilename == NULL) {
- log_error(LOG_ARGS, "Could not prepare sub list mail");
- exit(EXIT_FAILURE);
- }
+ txt = open_text(listdir, "list", NULL, NULL, subtype_strs[SUB_ALL],
+ "listsubs");
+ MY_ASSERT(txt);
+ queuefilename = prepstdreply(txt, listdir, "$listowner$", emailaddr, NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
fd = open(queuefilename, O_WRONLY);
if(fd < 0) {
}
if(lseek(fd, 0, SEEK_END) < 0) {
- log_error(LOG_ARGS, "Could not seek to send of file");
+ log_error(LOG_ARGS, "Could not seek to end of file");
exit(EXIT_FAILURE);
}