masqmail-0.2

annotate src/queue.c @ 171:349518b940db

added support for STARTTLS wrappers added the route config option `instant_helo' which causes masqmail, as SMTP client, not to wait for the server's 220 greeting. Instead if says EHLO right at once. You'll need this for STARTTLS wrappers that usually eat the greeting line.
author meillo@marmaro.de
date Thu, 22 Jul 2010 23:30:05 +0200
parents 83a182793503
children 087e99c7702a
rev   line source
meillo@0 1 /* MasqMail
meillo@0 2 Copyright (C) 1999-2001 Oliver Kurth
meillo@0 3
meillo@0 4 This program is free software; you can redistribute it and/or modify
meillo@0 5 it under the terms of the GNU General Public License as published by
meillo@0 6 the Free Software Foundation; either version 2 of the License, or
meillo@0 7 (at your option) any later version.
meillo@0 8
meillo@0 9 This program is distributed in the hope that it will be useful,
meillo@0 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
meillo@0 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
meillo@0 12 GNU General Public License for more details.
meillo@0 13
meillo@0 14 You should have received a copy of the GNU General Public License
meillo@0 15 along with this program; if not, write to the Free Software
meillo@0 16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
meillo@0 17 */
meillo@0 18
meillo@0 19 #include <sys/stat.h>
meillo@0 20 #include <glob.h>
meillo@0 21
meillo@15 22 #include "masqmail.h"
meillo@15 23
meillo@10 24 static void
meillo@10 25 mix_arr(int *buf, int len)
meillo@0 26 {
meillo@10 27 int i;
meillo@0 28
meillo@10 29 for (i = 0; i < len; i++)
meillo@10 30 buf[i] = i;
meillo@10 31 for (i = 0; i < len - 1; i++) {
meillo@10 32 int j = (int) ((float) (len - i) * ((float) rand()) / (RAND_MAX + 1.0));
meillo@10 33 int tmp;
meillo@0 34
meillo@10 35 if (i != j) {
meillo@10 36 tmp = buf[i];
meillo@10 37 buf[i] = buf[j];
meillo@10 38 buf[j] = tmp;
meillo@10 39 }
meillo@10 40 }
meillo@0 41 }
meillo@0 42
meillo@10 43 GList*
meillo@10 44 read_queue(gboolean do_readdata)
meillo@0 45 {
meillo@10 46 GList *msg_list = NULL;
meillo@10 47 glob_t gl;
meillo@10 48 gchar *pattern;
meillo@10 49 int i, *idx_arr;
meillo@0 50
meillo@38 51 /* Escaping the question marks prevents them from being
meillo@38 52 interpreted as trigraphs */
meillo@38 53 pattern = g_strdup_printf("%s/input/?????\?-??\?-?\?-H", conf.spool_dir);
meillo@10 54 gl.gl_offs = 0;
meillo@10 55 glob(pattern, 0, NULL, &gl);
meillo@0 56
meillo@10 57 g_free(pattern);
meillo@0 58
meillo@10 59 DEBUG(4) {
meillo@10 60 int i;
meillo@10 61 for (i = 0; i < gl.gl_pathc; i++) {
meillo@10 62 debugf("spoolfile: %s\n", gl.gl_pathv[i]);
meillo@10 63 }
meillo@10 64 }
meillo@0 65
meillo@10 66 idx_arr = g_malloc(sizeof(int) * gl.gl_pathc);
meillo@10 67 mix_arr(idx_arr, gl.gl_pathc);
meillo@0 68
meillo@10 69 for (i = 0; i < gl.gl_pathc; i++) {
meillo@10 70 gchar *uid;
meillo@0 71
meillo@10 72 /* copy 13 chars, offset spooldir path + 7 chars for /input/ */
meillo@10 73 /* uid length = 6 chars + '-' + 3 chars + '-' + 2 = 13 chars */
meillo@10 74 uid = g_strndup(&(gl.gl_pathv[idx_arr[i]][strlen(conf.spool_dir) + 7]), 13);
meillo@0 75
meillo@10 76 DEBUG(5) debugf("uid: %s\n", uid);
meillo@0 77
meillo@10 78 msg_list = g_list_append(msg_list, msg_spool_read(uid, do_readdata));
meillo@0 79
meillo@10 80 DEBUG(5) debugf("after read spool file for %s\n", uid);
meillo@0 81
meillo@10 82 g_free(uid);
meillo@10 83 }
meillo@10 84 return msg_list;
meillo@0 85 }
meillo@0 86
meillo@10 87 gboolean
meillo@10 88 queue_run()
meillo@0 89 {
meillo@10 90 GList *msg_list;
meillo@10 91 gboolean ok = TRUE;
meillo@0 92
meillo@10 93 logwrite(LOG_NOTICE, "Starting queue run.\n");
meillo@0 94
meillo@10 95 msg_list = read_queue(FALSE);
meillo@0 96
meillo@10 97 if (msg_list != NULL) {
meillo@10 98 ok = deliver_msg_list(msg_list, DLVR_ALL);
meillo@10 99 destroy_msg_list(msg_list);
meillo@114 100 logwrite(LOG_NOTICE, " deliver_msg_list()=%d.\n", ok);
meillo@10 101 }
meillo@10 102 logwrite(LOG_NOTICE, "Finished queue run.\n");
meillo@0 103
meillo@10 104 return ok;
meillo@0 105 }
meillo@0 106
meillo@10 107 gboolean
meillo@10 108 queue_run_online()
meillo@0 109 {
meillo@10 110 GList *msg_list = read_queue(FALSE);
meillo@10 111 gboolean ok = TRUE;
meillo@0 112
meillo@10 113 logwrite(LOG_NOTICE, "Starting online queue run.\n");
meillo@10 114 if (msg_list != NULL) {
meillo@10 115 ok = deliver_msg_list(msg_list, DLVR_ONLINE);
meillo@10 116 destroy_msg_list(msg_list);
meillo@10 117 }
meillo@10 118 logwrite(LOG_NOTICE, "Finished online queue run.\n");
meillo@0 119
meillo@10 120 return ok;
meillo@0 121 }
meillo@0 122
meillo@10 123 static gchar*
meillo@10 124 format_difftime(double secs)
meillo@0 125 {
meillo@10 126 if (secs > 86400)
meillo@10 127 return g_strdup_printf("%.1fd", secs / 86400);
meillo@10 128 else if (secs > 3600)
meillo@10 129 return g_strdup_printf("%.1fh", secs / 3600);
meillo@10 130 else if (secs > 60)
meillo@10 131 return g_strdup_printf("%.1fm", secs / 60);
meillo@10 132 else
meillo@10 133 return g_strdup_printf("%.0fs", secs);
meillo@10 134 }
meillo@0 135
meillo@10 136 void
meillo@10 137 queue_list()
meillo@0 138 {
meillo@10 139 GList *msg_list;
meillo@10 140 GList *msg_node;
meillo@0 141
meillo@10 142 msg_list = read_queue(FALSE);
meillo@0 143
meillo@82 144 if (msg_list == NULL) {
meillo@82 145 printf("mail queue is empty.\n");
meillo@82 146 return;
meillo@82 147 }
meillo@0 148
meillo@82 149 foreach(msg_list, msg_node) {
meillo@82 150 message *msg = (message *) (msg_node->data);
meillo@82 151 GList *rcpt_node;
meillo@82 152 gchar *size_str = NULL;
meillo@82 153 gchar *time_str = NULL;
meillo@82 154 gchar *host_str = NULL;
meillo@82 155 gchar *ident_str = NULL;
meillo@0 156
meillo@82 157 if (msg->data_size >= 0)
meillo@82 158 size_str = g_strdup_printf(" size=%d", msg->data_size);
meillo@82 159 if (msg->received_time > 0) {
meillo@82 160 gchar *tmp_str;
meillo@82 161 time_str = g_strdup_printf(" age=%s", tmp_str = format_difftime(difftime(time(NULL), msg->received_time)));
meillo@82 162 g_free(tmp_str);
meillo@82 163 }
meillo@82 164 if (msg->received_host != NULL)
meillo@82 165 host_str = g_strdup_printf(" host=%s", msg->received_host);
meillo@82 166 if (msg->ident != NULL)
meillo@82 167 ident_str = g_strdup_printf(" ident=%s", msg->ident);
meillo@0 168
meillo@82 169 printf("%s <= %s%s%s%s%s\n", msg->uid, addr_string(msg->return_path), size_str ? size_str : "",
meillo@82 170 time_str ? time_str : "", host_str ? host_str : "", ident_str ? ident_str : "");
meillo@0 171
meillo@82 172 if (size_str)
meillo@82 173 g_free(size_str);
meillo@82 174 if (time_str)
meillo@82 175 g_free(time_str);
meillo@82 176 if (host_str)
meillo@82 177 g_free(host_str);
meillo@82 178 if (ident_str)
meillo@82 179 g_free(ident_str);
meillo@10 180
meillo@82 181 foreach(msg->rcpt_list, rcpt_node) {
meillo@82 182 address *rcpt = (address *) (rcpt_node->data);
meillo@82 183
meillo@82 184 printf(" %s %s\n", addr_is_delivered(rcpt) ? "=>" : (addr_is_failed(rcpt) ? "!=" : "=="), addr_string(rcpt));
meillo@10 185 }
meillo@82 186 g_free(msg);
meillo@82 187 }
meillo@10 188 }
meillo@10 189
meillo@10 190 gboolean
meillo@10 191 queue_delete(gchar * uid)
meillo@0 192 {
meillo@10 193 gboolean hdr_ok = TRUE;
meillo@10 194 gboolean dat_ok = TRUE;
meillo@10 195 gchar *hdr_name = g_strdup_printf("%s/input/%s-H", conf.spool_dir, uid);
meillo@10 196 gchar *dat_name = g_strdup_printf("%s/input/%s-D", conf.spool_dir, uid);
meillo@10 197 struct stat stat_buf;
meillo@0 198
meillo@82 199 if (!spool_lock(uid)) {
meillo@10 200 fprintf(stderr, "message %s is locked.\n", uid);
meillo@10 201 return FALSE;
meillo@10 202 }
meillo@0 203
meillo@82 204 if (stat(hdr_name, &stat_buf) == 0) {
meillo@82 205 if (unlink(hdr_name) != 0) {
meillo@82 206 fprintf(stderr, "could not unlink %s: %s\n", hdr_name, strerror(errno));
meillo@82 207 hdr_ok = FALSE;
meillo@82 208 }
meillo@82 209 } else {
meillo@82 210 fprintf(stderr, "could not stat file %s: %s\n", hdr_name, strerror(errno));
meillo@82 211 hdr_ok = FALSE;
meillo@82 212 }
meillo@82 213 if (stat(dat_name, &stat_buf) == 0) {
meillo@82 214 if (unlink(dat_name) != 0) {
meillo@82 215 fprintf(stderr, "could not unlink %s: %s\n", dat_name, strerror(errno));
meillo@82 216 dat_ok = FALSE;
meillo@82 217 }
meillo@82 218 } else {
meillo@82 219 fprintf(stderr, "could not stat file %s: %s\n", dat_name, strerror(errno));
meillo@82 220 dat_ok = FALSE;
meillo@82 221 }
meillo@82 222 printf("message %s deleted\n", uid);
meillo@82 223
meillo@82 224 spool_unlock(uid);
meillo@82 225
meillo@10 226 return (dat_ok && hdr_ok);
meillo@0 227 }