/*
* Copyright (C) 2002, 2003, 2004 Mads Martin Joergensen <mmj at mmj.dk>
- * Copyright (C) 2022-2023 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (C) 2022-2024 Baptiste Daroussin <bapt@FreeBSD.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
void ml_init(struct ml *ml);
bool ml_open(struct ml *ml, bool checkuser);
void ml_close(struct ml *ml);
+bool send_probe(struct ml *ml, const char *addr);
#define MY_ASSERT(expression) if (!(expression)) { \
errno = 0; \
/*
* Copyright (C) 2004 Mads Martin Joergensen <mmj at mmj.dk>
* Copyright (C) 2011 Ben Schmidt <mail_ben_schmidt at yahoo.com.au>
- * Copyright (C) 2023 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (C) 2023-2024 Baptiste Daroussin <bapt@FreeBSD.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
void finish_memory_lines(memory_lines_state *s);
file_lines_state *init_file_lines(const char *filename, char truncate);
+file_lines_state *init_file_lines_fd(int fd, char truncate);
void rewind_file_lines(void *state);
const char *get_file_line(void *state);
void finish_file_lines(file_lines_state *s);
#include "utils.h"
#include "send_mail.h"
-static void
-unlink_bounce(struct ml *ml, const char *to)
+void
+do_probe(struct ml *ml, const char *addr)
{
- char *tmpstr, *a, *probefile;
-
- /* error, so remove the probefile */
- tmpstr = xstrdup(to);
- a = strchr(tmpstr, '@');
- MY_ASSERT(a);
- *a = '=';
- xasprintf(&probefile, "bounce/%s-probe", tmpstr);
- unlinkat(ml->fd, probefile, 0);
- free(probefile);
- free(tmpstr);
-}
-
-void do_probe(struct ml *ml, const char *addr)
-{
- text *txt;
- file_lines_state *fls;
- char *myaddr, *from, *a, *queuefilename;
- char *probefile;
- int fd;
- time_t t;
- struct mail mail = { 0 };
-
- myaddr = lowercase(addr);
-
- gen_addr_cookie(from, ml, "bounces-probe-", myaddr)
-
- a = strrchr(myaddr, '=');
- if (!a) {
- free(myaddr);
- free(from);
- log_error(LOG_ARGS, "do_probe(): malformed address");
- exit(EXIT_FAILURE);
-
- }
- *a = '@';
-
- txt = open_text(ml->fd, "probe", NULL, NULL, NULL, "bounce-probe");
- MY_ASSERT(txt);
- register_default_unformatted(txt, ml);
- register_unformatted(txt, "bouncenumbers", "%bouncenumbers%"); /* DEPRECATED */
- fls = init_file_lines(addr, ':');
- register_formatted(txt, "bouncenumbers",
- rewind_file_lines, get_file_line, fls);
- queuefilename = prepstdreply(txt, ml, "$listowner$", myaddr, NULL);
- MY_ASSERT(queuefilename);
- close_text(txt);
-
- finish_file_lines(fls);
-
- xasprintf(&probefile, "bounce/%s-probe", addr);
- t = time(NULL);
- fd = openat(ml->fd, probefile, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR);
- if(fd < 0)
- log_error(LOG_ARGS, "Could not open %s", probefile);
- else
- if (dprintf(fd, "%ld", (long int)t) < 0)
- log_error(LOG_ARGS, "Could not write time in probe");
- free(probefile);
-
- mail.to = myaddr;
- mail.from = from;
- mail.fp = fopen(queuefilename, "r");
- if (!send_single_mail(&mail, ml, false)) {
- unlink_bounce(ml, myaddr);
- exit(EXIT_FAILURE);
- }
- fclose(mail.fp);
- exit(EXIT_SUCCESS);
+ if (send_probe(ml, addr))
+ exit(EXIT_SUCCESS);
+ exit(EXIT_FAILURE);
}
static void print_help(const char *prg)
/*
- * Copyright (C) 2021-2023 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (C) 2021-2024 Baptiste Daroussin <bapt@FreeBSD.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
#include <err.h>
#include "getlistdelim.h"
+#include "send_mail.h"
#include "mlmmj.h"
#include "utils.h"
#include "log_error.h"
#include "gethdrline.h"
#include "mygetline.h"
#include "subscriberfuncs.h"
+#include "prepstdreply.h"
#include "find_email_adr.h"
#include "strgen.h"
#include "ctrlvalue.h"
+bool
+send_probe(struct ml *ml, const char *addr)
+{
+ text *txt;
+ file_lines_state *fls;
+ char *myaddr, *from, *a, *queuefilename;
+ char *probefile;
+ int fd, bfd;
+ time_t t;
+ struct mail mail = { 0 };
+
+ myaddr = lowercase(addr);
+
+ gen_addr_cookie(from, ml, "bounces-probe-", myaddr)
+
+ a = strrchr(myaddr, '=');
+ if (!a) {
+ free(myaddr);
+ free(from);
+ log_error(LOG_ARGS, "do_probe(): malformed address");
+ return (false);
+ }
+ *a = '@';
+ bfd = openat(ml->fd, "bounce", O_DIRECTORY);
+ if (bfd == -1) {
+ free(myaddr);
+ free(from);
+ log_error(LOG_ARGS, "impossible to open bounce directory");
+ return (false);
+ }
+
+ txt = open_text(ml->fd, "probe", NULL, NULL, NULL, "bounce-probe");
+ MY_ASSERT(txt);
+ register_default_unformatted(txt, ml);
+ register_unformatted(txt, "bouncenumbers", "%bouncenumbers%"); /* DEPRECATED */
+ fls = init_file_lines_fd(openat(bfd, addr, O_RDONLY), ':');
+ register_formatted(txt, "bouncenumbers",
+ rewind_file_lines, get_file_line, fls);
+ queuefilename = prepstdreply(txt, ml, "$listowner$", myaddr, NULL);
+ MY_ASSERT(queuefilename);
+ close_text(txt);
+ finish_file_lines(fls);
+
+ xasprintf(&probefile, "%s-probe", addr);
+ t = time(NULL);
+ fd = openat(bfd, probefile, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR);
+ if(fd < 0)
+ log_error(LOG_ARGS, "Could not open %s", probefile);
+ else
+ if (dprintf(fd, "%ld", (long int)t) < 0)
+ log_error(LOG_ARGS, "Could not write time in probe");
+
+ mail.to = myaddr;
+ mail.from = from;
+ mail.fp = fopen(queuefilename, "r");
+ if (!send_single_mail(&mail, ml, false)) {
+ unlinkat(bfd, probefile, 0);
+ free(probefile);
+ return (false);
+ }
+ free(probefile);
+ fclose(mail.fp);
+ return (true);
+}
+
+
bool
parse_lastdigest(char *line, long *lastindex, time_t *lasttime,
long *lastissue, const char **errstr)
}
-file_lines_state *init_file_lines(const char *filename, char truncate)
+file_lines_state *
+init_file_lines(const char *filename, char truncate)
{
file_lines_state *s = xcalloc(1, sizeof(file_lines_state));
s->filename = xstrdup(filename);
return s;
}
+file_lines_state
+*init_file_lines_fd(int fd, char truncate)
+{
+ file_lines_state *s;
+
+ if (fd == -1)
+ return (NULL);
+ s = xcalloc(1, sizeof(file_lines_state));
+ s->fp = fdopen(fd, "r");
+ s->truncate = truncate;
+ return (s);
+}
+
void rewind_file_lines(void *state)
{
ATF_TC_WITHOUT_HEAD(gethdrline);
ATF_TC_WITHOUT_HEAD(readlf);
ATF_TC_WITHOUT_HEAD(mod_get_addr_type);
+ATF_TC_WITHOUT_HEAD(send_probe);
ATF_TC_BODY(random_int, tc)
{
atf_utils_wait(p, 1, "", "");
}
+ATF_TC_BODY(send_probe, tc)
+{
+ char *dir;
+ init_ml(true);
+ struct ml ml;
+ ml_init(&ml);
+ ml.dir = "list";
+ ml_open(&ml, false);
+ rmdir("list/text");
+ xasprintf(&dir, "%s/../listtexts/en",
+ atf_tc_get_config_var(tc, "srcdir"));
+
+ symlink(dir, "list/text");
+ atf_utils_create_file("list/control/smtpport", "25678");
+ atf_utils_create_file("list/control/smtphelo", "heloname");
+ int smtppipe[2];
+ ATF_REQUIRE(socketpair(AF_UNIX, SOCK_STREAM, 0, smtppipe) >= 0);
+ pid_t p2 = single_mail_reception(smtppipe[1]);
+ atf_utils_readline(smtppipe[0]);
+ pid_t p = atf_utils_fork();
+ if (p == 0) {
+ if (send_probe(&ml, "bapt=freebsd.org"))
+ exit(0);
+ exit(1);
+ }
+ atf_utils_wait(p2, 0, "save:mailout.txt", "");
+ atf_utils_wait(p, 0, "", "");
+
+ if (!atf_utils_grep_file("Some messages to you could not be delivered", "mailout.txt")) {
+ atf_utils_cat_file("mailout.txt", "");
+ atf_tc_fail("invalid file");
+ }
+
+ p = atf_utils_fork();
+ if (p == 0) {
+ if (send_probe(&ml, "bapt@freebsd.org"))
+ exit(0);
+ exit(1);
+ }
+ atf_utils_wait(p, 1, "", "");
+
+ atf_utils_create_file("list/bounce/bapt=freebsd.org", "1234:blabla\n");
+ p2 = single_mail_reception(smtppipe[1]);
+ atf_utils_readline(smtppipe[0]);
+ p = atf_utils_fork();
+ if (p == 0) {
+ if (send_probe(&ml, "bapt=freebsd.org"))
+ exit(0);
+ exit(1);
+ }
+ atf_utils_wait(p2, 0, "save:mailout.txt", "");
+ atf_utils_wait(p, 0, "", "");
+ if (!atf_utils_grep_file("1234", "mailout.txt")) {
+ atf_utils_cat_file("mailout.txt", ">");
+ atf_tc_fail("invalid mail sent");
+ }
+}
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, random_int);
ATF_TP_ADD_TC(tp, gethdrline);
ATF_TP_ADD_TC(tp, readlf);
ATF_TP_ADD_TC(tp, mod_get_addr_type);
+ ATF_TP_ADD_TC(tp, send_probe);
return (atf_no_error());
}