+1.2.8
+ o Make sure the resend of queue files will not loop indefinately
+ o Make Date: header RFC2822 compliant (Jakob Hirsch)
+ o Add -s switch to mlmmj-{,un}sub to control whether or not to send a mail
+ telling about already subscribed, or not subscribed when trying to
+ subscribe or unsubscribe (Christian Laursen)
1.2.7
o Remove old superflous cruft in the smtpreply reader function, making
mlmmj-send not segfault in rare cases when SIGTERM was sent
char *bouncelifestr;
pid_t childpid, pid;
struct stat st;
- int fromfd, tofd, fd, discarded = 0, status;
+ int fromfd, tofd, fd, status, err = 0;
time_t t, bouncelife = 0;
if(chdir(dirname) < 0) {
myfree(dirname);
while((dp = readdir(queuedir)) != NULL) {
- if(stat(dp->d_name, &st) < 0) {
- log_error(LOG_ARGS, "Could not stat(%s)",dp->d_name);
+ mailname = concatstr(3, listdir, "/queue/", dp->d_name);
+
+ if(stat(mailname, &st) < 0) {
+ log_error(LOG_ARGS, "Could not stat(%s)", mailname);
continue;
}
continue;
if(strchr(dp->d_name, '.')) {
- mailname = mystrdup(dp->d_name);
- ch = strchr(mailname, '.');
+ ch = strrchr(mailname, '.');
*ch = '\0';
- if(stat(mailname, &st) < 0)
- if(errno == ENOENT)
- unlink(dp->d_name);
+ if(stat(mailname, &st) < 0) {
+ if(errno == ENOENT) {
+ *ch = '.';
+ unlink(mailname);
+ }
+ }
myfree(mailname);
continue;
}
- mailname = concatstr(3, listdir, "/queue/", dp->d_name);
-
fromname = concatstr(2, mailname, ".mailfrom");
toname = concatstr(2, mailname, ".reciptto");
reptoname = concatstr(2, mailname, ".reply-to");
fromfd = open(fromname, O_RDONLY);
+ if(fromfd < 0)
+ err = errno;
tofd = open(toname, O_RDONLY);
- if(fromfd < 0 || tofd < 0) {
- if(discarded) {
- unlink(fromname);
- unlink(toname);
- unlink(reptoname);
- }
+ if((fromfd < 0 && err == ENOENT) ||
+ (tofd < 0 && errno == ENOENT)) {
+ unlink(mailname);
+ unlink(fromname);
+ unlink(toname);
+ unlink(reptoname);
myfree(mailname);
myfree(fromname);
myfree(toname);
myfree(reptoname);
if(fromfd >= 0)
close(fromfd);
+ if(tofd >= 0)
+ close(tofd);
continue;
}
from = mygetline(fromfd);
chomp(from);
close(fromfd);
- unlink(fromname);
myfree(fromname);
to = mygetline(tofd);
chomp(to);
close(tofd);
- unlink(toname);
myfree(toname);
fd = open(reptoname, O_RDONLY);
if(fd < 0) {
repto = mygetline(fd);
chomp(repto);
close(fd);
- unlink(reptoname);
myfree(reptoname);
}
if(sendres) {
/* error, so keep it in the queue */
deletewhensent = 0;
- /* dump date we want when resending */
+ /* dump data we want when resending first check
+ * if it already exists. In that case continue */
tmpstr = concatstr(2, mailfilename, ".mailfrom");
+ if(stat(tmpstr, &st) == 0) {
+ myfree(tmpstr);
+ break;
+ }
tmpfd = open(tmpstr, O_WRONLY|O_CREAT|O_TRUNC,
S_IRUSR|S_IWUSR);
myfree(tmpstr);
}
close(tmpfd);
tmpstr = concatstr(2, mailfilename, ".reciptto");
+ if(stat(tmpstr, &st) == 0) {
+ myfree(tmpstr);
+ break;
+ }
tmpfd = open(tmpstr, O_WRONLY|O_CREAT|O_TRUNC,
S_IRUSR|S_IWUSR);
myfree(tmpstr);
if(replyto) {
tmpstr = concatstr(2, mailfilename,
".reply-to");
+ if(stat(tmpstr, &st) == 0) {
+ myfree(tmpstr);
+ break;
+ }
tmpfd = open(tmpstr, O_WRONLY|O_CREAT|O_TRUNC,
S_IRUSR|S_IWUSR);
myfree(tmpstr);
static void print_help(const char *prg)
{
printf("Usage: %s -L /path/to/list -a john@doe.org "
- "[-c] [-C] [-h]\n [-L] [-d | -n] [-U] [-V]\n"
+ "[-c] [-C] [-h]\n [-L] [-d | -n] [-s] [-U] [-V]\n"
" -a: Email address to subscribe \n"
" -c: Send welcome mail\n"
" -C: Request mail confirmation\n"
" -h: This help\n"
" -L: Full path to list directory\n"
" -n: Subscribe to no mail version of list\n"
+ " -s: Don't send a mail to the subscriber if already subscribed\n"
" -U: Don't switch to the user id of the listdir owner\n"
" -V: Print version\n"
"When no options are specified, subscription silently "
char *sublockname;
int subconfirm = 0, confirmsub = 0, opt, subfilefd, lock, notifysub;
int changeuid = 1, status, digest = 0, nomail = 0;
- int groupwritable = 0, sublock, sublockfd;
+ int groupwritable = 0, sublock, sublockfd, nogensubscribed = 0;
size_t len;
off_t suboff;
struct stat st;
mlmmjsend = concatstr(2, bindir, "/mlmmj-send");
myfree(bindir);
- while ((opt = getopt(argc, argv, "hcCdnVUL:a:")) != -1) {
+ while ((opt = getopt(argc, argv, "hcCdnsVUL:a:")) != -1) {
switch(opt) {
case 'a':
address = optarg;
case 'n':
nomail = 1;
break;
+ case 's':
+ nogensubscribed = 1;
+ break;
case 'U':
changeuid = 0;
break;
unlink(sublockname);
myfree(sublockname);
- generate_subscribed(listdir, address, mlmmjsend);
+ if(!nogensubscribed)
+ generate_subscribed(listdir, address, mlmmjsend);
return EXIT_SUCCESS;
}
static void print_help(const char *prg)
{
printf("Usage: %s -L /path/to/list -a john@doe.org "
- "[-c] [-C] [-h] [-L] [-d | -n] [-V]\n"
+ "[-c] [-C] [-h] [-L] [-d | -n] [-s] [-V]\n"
" -a: Email address to unsubscribe \n"
" -c: Send goodbye mail\n"
" -C: Request mail confirmation\n"
" -h: This help\n"
" -L: Full path to list directory\n"
" -n: Subscribe to no mail version of list\n"
+ " -s: Don't send a mail to the address if not subscribed\n"
" -U: Don't switch to the user id of the listdir owner\n"
" -V: Print version\n"
"When no options are specified, unsubscription silently "
int subread, subwrite, rlock, wlock, opt, unsubres, status, nomail = 0;
int confirmunsub = 0, unsubconfirm = 0, notifysub = 0, digest = 0;
int changeuid = 1, groupwritable = 0, sublock, sublockfd;
+ int nogennotsubscribed = 0;
char *listaddr, *listdir = NULL, *address = NULL, *subreadname = NULL;
char *subwritename, *mlmmjsend, *bindir, *subdir;
char *subddirname, *sublockname;
mlmmjsend = concatstr(2, bindir, "/mlmmj-send");
myfree(bindir);
- while ((opt = getopt(argc, argv, "hcCdnVUL:a:")) != -1) {
+ while ((opt = getopt(argc, argv, "hcCdnVUL:a:s")) != -1) {
switch(opt) {
case 'L':
listdir = optarg;
case 'h':
print_help(argv[0]);
break;
+ case 's':
+ nogennotsubscribed = 1;
+ break;
case 'U':
changeuid = 0;
break;
myfree(subddirname);
myfree(listaddr);
- generate_notsubscribed(listdir, address, mlmmjsend);
+ if(!nogennotsubscribed) {
+ generate_notsubscribed(listdir, address, mlmmjsend);
+ }
exit(EXIT_SUCCESS);
}