masqmail-0.2

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