comparison src/deliver.c @ 10:26e34ae9a3e3

changed indention and line wrapping to a more consistent style
author meillo@marmaro.de
date Mon, 27 Oct 2008 16:23:10 +0100
parents 08114f7dcc23
children 9fb7ddbaf129
comparison
equal deleted inserted replaced
9:31cc8a89cb74 10:26e34ae9a3e3
23 #include <netdb.h> 23 #include <netdb.h>
24 24
25 /* collect failed/defered rcpts for failure/warning messages */ 25 /* collect failed/defered rcpts for failure/warning messages */
26 /* returns TRUE if either there are no failures or a 26 /* returns TRUE if either there are no failures or a
27 failure message has been successfully sent */ 27 failure message has been successfully sent */
28 gboolean delivery_failures(message *msg, GList *rcpt_list, gchar *err_fmt, ...) 28 gboolean
29 { 29 delivery_failures(message * msg, GList * rcpt_list, gchar * err_fmt, ...)
30 gboolean ok_fail = TRUE, ok_warn = TRUE; 30 {
31 time_t now = time(NULL); 31 gboolean ok_fail = TRUE, ok_warn = TRUE;
32 32 time_t now = time(NULL);
33 GList *failed_list = NULL, *defered_list = NULL, *rcpt_node; 33
34 va_list args; 34 GList *failed_list = NULL, *defered_list = NULL, *rcpt_node;
35 va_start(args, err_fmt); 35 va_list args;
36 36 va_start(args, err_fmt);
37 foreach(rcpt_list, rcpt_node){ 37
38 address *rcpt = (address *)(rcpt_node->data); 38 foreach(rcpt_list, rcpt_node) {
39 39 address *rcpt = (address *) (rcpt_node->data);
40 if(addr_is_defered(rcpt)){ 40
41 if((now - msg->received_time) >= conf.max_defer_time){ 41 if (addr_is_defered(rcpt)) {
42 addr_mark_failed(rcpt); 42 if ((now - msg->received_time) >= conf.max_defer_time) {
43 }else 43 addr_mark_failed(rcpt);
44 defered_list = g_list_prepend(defered_list, rcpt); 44 } else
45 } 45 defered_list = g_list_prepend(defered_list, rcpt);
46 if(addr_is_failed(rcpt)) 46 }
47 failed_list = g_list_prepend(failed_list, rcpt); 47 if (addr_is_failed(rcpt))
48 } 48 failed_list = g_list_prepend(failed_list, rcpt);
49 if(failed_list != NULL){ 49 }
50 ok_fail = fail_msg(msg, conf.errmsg_file, failed_list, err_fmt, args); 50 if (failed_list != NULL) {
51 g_list_free(failed_list); 51 ok_fail = fail_msg(msg, conf.errmsg_file, failed_list, err_fmt, args);
52 } 52 g_list_free(failed_list);
53 if(defered_list != NULL){ 53 }
54 ok_warn = warn_msg(msg, conf.warnmsg_file, defered_list, err_fmt, args); 54 if (defered_list != NULL) {
55 g_list_free(defered_list); 55 ok_warn = warn_msg(msg, conf.warnmsg_file, defered_list, err_fmt, args);
56 } 56 g_list_free(defered_list);
57 va_end(args); 57 }
58 return ok_fail && ok_warn; 58 va_end(args);
59 } 59 return ok_fail && ok_warn;
60 60 }
61 static gint _g_list_strcasecmp(gconstpointer a, gconstpointer b) 61
62 { 62 static gint
63 return (gint)strcasecmp(a, b); 63 _g_list_strcasecmp(gconstpointer a, gconstpointer b)
64 } 64 {
65 65 return (gint) strcasecmp(a, b);
66 gboolean deliver_local(msg_out *msgout) 66 }
67 { 67
68 message *msg = msgout->msg; 68 gboolean
69 GList *rcpt_list = msgout->rcpt_list; 69 deliver_local(msg_out * msgout)
70 GList *rcpt_node; 70 {
71 gboolean ok = TRUE, flag = FALSE, ok_fail = FALSE; 71 message *msg = msgout->msg;
72 72 GList *rcpt_list = msgout->rcpt_list;
73 DEBUG(5) debugf("deliver_local entered\n"); 73 GList *rcpt_node;
74 74 gboolean ok = TRUE, flag = FALSE, ok_fail = FALSE;
75 flag = (msg->data_list == NULL); 75
76 if(flag){ 76 DEBUG(5) debugf("deliver_local entered\n");
77 if(!(ok = spool_read_data(msg))){ 77
78 logwrite(LOG_ALERT, "could not open data spool file for %s\n", 78 flag = (msg->data_list == NULL);
79 msg->uid); 79 if (flag) {
80 } 80 if (!(ok = spool_read_data(msg))) {
81 } 81 logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid);
82 if(!ok) return FALSE; 82 }
83 83 }
84 ok = FALSE; 84 if (!ok)
85 for(rcpt_node = g_list_first(rcpt_list); 85 return FALSE;
86 rcpt_node; 86
87 rcpt_node = g_list_next(rcpt_node)){ 87 ok = FALSE;
88 GList *hdr_list; 88 for (rcpt_node = g_list_first(rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) {
89 address *rcpt = (address *)(rcpt_node->data); 89 GList *hdr_list;
90 address *env_addr = addr_find_ancestor(rcpt); 90 address *rcpt = (address *) (rcpt_node->data);
91 address *ret_path = msg->return_path; 91 address *env_addr = addr_find_ancestor(rcpt);
92 header *retpath_hdr, *envto_hdr; 92 address *ret_path = msg->return_path;
93 93 header *retpath_hdr, *envto_hdr;
94 /* we need a private copy of the hdr list because we add headers here 94
95 that belong to the rcpt only. 95 /* we need a private copy of the hdr list because we add headers here
96 g_list_copy copies only the nodes, so it is safe to 96 that belong to the rcpt only.
97 g_list_free it 97 g_list_copy copies only the nodes, so it is safe to
98 */ 98 g_list_free it
99 hdr_list = g_list_copy(msg->hdr_list); 99 */
100 retpath_hdr = create_header(HEAD_ENVELOPE_TO, 100 hdr_list = g_list_copy(msg->hdr_list);
101 "Envelope-to: %s\n", addr_string(env_addr)); 101 retpath_hdr = create_header(HEAD_ENVELOPE_TO, "Envelope-to: %s\n", addr_string(env_addr));
102 envto_hdr = create_header(HEAD_RETURN_PATH, 102 envto_hdr = create_header(HEAD_RETURN_PATH, "Return-path: %s\n", addr_string(ret_path));
103 "Return-path: %s\n", addr_string(ret_path)); 103
104 104 hdr_list = g_list_prepend(hdr_list, envto_hdr);
105 hdr_list = g_list_prepend(hdr_list, envto_hdr); 105 hdr_list = g_list_prepend(hdr_list, retpath_hdr);
106 hdr_list = g_list_prepend(hdr_list, retpath_hdr); 106
107 107 if (rcpt->local_part[0] == '|') {
108 if(rcpt->local_part[0] == '|'){ 108 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid);
109 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); 109 if (pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]),
110 if(pipe_out(msg, hdr_list, rcpt, &(rcpt->local_part[1]), 110 (conf.pipe_fromline ? MSGSTR_FROMLINE : 0)
111 (conf.pipe_fromline ? MSGSTR_FROMLINE : 0) | 111 | (conf.pipe_fromhack ? MSGSTR_FROMHACK : 0))) {
112 (conf.pipe_fromhack ? MSGSTR_FROMHACK : 0))){ 112 logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", msg->uid, rcpt->local_part, env_addr->local_part, env_addr->domain);
113 logwrite(LOG_NOTICE, "%s => %s <%s@%s> with pipe\n", 113 addr_mark_delivered(rcpt);
114 msg->uid, rcpt->local_part, 114 ok = TRUE;
115 env_addr->local_part, env_addr->domain 115 } else {
116 ); 116 if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) {
117 addr_mark_delivered(rcpt); 117 addr_mark_failed(rcpt);
118 ok = TRUE; 118 } else {
119 }else{ 119 addr_mark_defered(rcpt); /* has no effect yet, except that mail remains in spool */
120 if((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)){ 120 }
121 addr_mark_failed(rcpt); 121 }
122 }else{ 122 } else {
123 addr_mark_defered(rcpt); /* has no effect yet, 123 /* figure out which mailbox type should be used for this user */
124 except that mail remains in spool */ 124 gchar *user = rcpt->local_part;
125 } 125 gchar *mbox_type = conf.mbox_default;
126 } 126
127 }else{ 127 if (g_list_find_custom (conf.mbox_users, user, _g_list_strcasecmp) != NULL)
128 /* figure out which mailbox type should be used for this user */ 128 mbox_type = "mbox";
129 gchar *user = rcpt->local_part; 129 else if (g_list_find_custom (conf.mda_users, user, _g_list_strcasecmp) != NULL)
130 gchar *mbox_type = conf.mbox_default; 130 mbox_type = "mda";
131 131 else if (g_list_find_custom (conf.maildir_users, user, _g_list_strcasecmp) != NULL)
132 if(g_list_find_custom(conf.mbox_users, user, _g_list_strcasecmp) != NULL) 132 mbox_type = "maildir";
133 mbox_type = "mbox"; 133
134 else if(g_list_find_custom(conf.mda_users, user, _g_list_strcasecmp) != NULL) 134 if (strcmp(mbox_type, "mbox") == 0) {
135 mbox_type = "mda"; 135 DEBUG(1) debugf("attempting to deliver %s with mbox\n", msg->uid);
136 else if(g_list_find_custom(conf.maildir_users, user, _g_list_strcasecmp) != NULL) 136 if (append_file(msg, hdr_list, rcpt->local_part)) {
137 mbox_type = "maildir"; 137 if (env_addr != rcpt) {
138 138 logwrite(LOG_NOTICE, "%s => %s@%s <%s@%s> with mbox\n",
139 if(strcmp(mbox_type, "mbox") == 0){ 139 msg->uid, rcpt->local_part, rcpt->domain,
140 DEBUG(1) debugf("attempting to deliver %s with mbox\n", msg->uid); 140 env_addr->local_part, env_addr->domain);
141 if(append_file(msg, hdr_list, rcpt->local_part)){ 141 } else {
142 if(env_addr != rcpt){ 142 logwrite(LOG_NOTICE, "%s => <%s@%s> with mbox\n",
143 logwrite(LOG_NOTICE, "%s => %s@%s <%s@%s> with mbox\n", 143 msg->uid, rcpt->local_part, rcpt->domain);
144 msg->uid, rcpt->local_part, rcpt->domain, 144 }
145 env_addr->local_part, env_addr->domain 145 addr_mark_delivered(rcpt);
146 ); 146 ok = TRUE;
147 }else{ 147 } else {
148 logwrite(LOG_NOTICE, "%s => <%s@%s> with mbox\n", 148 if (errno != EAGAIN) { /* prevents 'Resource temporarily unavailable (11)' */
149 msg->uid, rcpt->local_part, rcpt->domain); 149 addr_mark_failed(rcpt);
150 } 150 } else {
151 addr_mark_delivered(rcpt); 151 addr_mark_defered(rcpt);
152 ok = TRUE; 152 }
153 }else{ 153 }
154 if(errno != EAGAIN){ /* prevents 'Resource temporarily unavailable (11)' */ 154
155 addr_mark_failed(rcpt); 155 } else if (strcmp(mbox_type, "mda") == 0) {
156 }else{ 156 if (conf.mda) {
157 addr_mark_defered(rcpt); 157 gchar *cmd = g_malloc(256);
158 } 158 GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt);
159 } 159
160 160 DEBUG(1) debugf("attempting to deliver %s with mda\n", msg->uid);
161 }else if(strcmp(mbox_type, "mda") == 0){ 161
162 if(conf.mda){ 162 if (expand(var_table, conf.mda, cmd, 256)) {
163 gchar *cmd = g_malloc(256); 163
164 GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); 164 if (pipe_out(msg, hdr_list, rcpt, cmd, (conf.mda_fromline ? MSGSTR_FROMLINE : 0)
165 165 | (conf.mda_fromhack ? MSGSTR_FROMHACK : 0))) {
166 DEBUG(1) debugf("attempting to deliver %s with mda\n", msg->uid); 166 logwrite(LOG_NOTICE, "%s => %s@%s with mda (cmd = '%s')\n",
167 167 msg->uid, rcpt->local_part, rcpt->domain, cmd);
168 if(expand(var_table, conf.mda, cmd, 256)){ 168 addr_mark_delivered(rcpt);
169 169 ok = TRUE;
170 if(pipe_out(msg, hdr_list, rcpt, cmd, 170 } else {
171 (conf.mda_fromline ? MSGSTR_FROMLINE : 0) | 171 if ((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)) {
172 (conf.mda_fromhack ? MSGSTR_FROMHACK : 0))){ 172 addr_mark_failed(rcpt);
173 logwrite(LOG_NOTICE, "%s => %s@%s with mda (cmd = '%s')\n", 173 } else {
174 msg->uid, rcpt->local_part, rcpt->domain, cmd 174 addr_mark_defered(rcpt); /* has no effect yet, except that mail remains in spool */
175 ); 175 }
176 addr_mark_delivered(rcpt); 176 }
177 ok = TRUE; 177 } else
178 }else{ 178 logwrite(LOG_ALERT, "could not expand string %s\n", conf.mda);
179 if((errno != (1024 + EX_TEMPFAIL)) && (errno != EAGAIN)){ 179
180 addr_mark_failed(rcpt); 180 destroy_table(var_table);
181 }else{ 181 } else
182 addr_mark_defered(rcpt); /* has no effect yet, 182 logwrite(LOG_ALERT, "mbox type is mda, but no mda command given in configuration\n");
183 except that mail remains in spool */
184 }
185 }
186 }else
187 logwrite(LOG_ALERT, "could not expand string %s\n", conf.mda);
188
189 destroy_table(var_table);
190 }else
191 logwrite(LOG_ALERT, "mbox type is mda, but no mda command given in configuration\n");
192 183
193 #ifdef ENABLE_MAILDIR 184 #ifdef ENABLE_MAILDIR
194 }else if(strcmp(mbox_type, "maildir") == 0){ 185 } else if (strcmp(mbox_type, "maildir") == 0) {
195 DEBUG(1) debugf("attempting to deliver %s with maildir\n", msg->uid); 186 DEBUG(1) debugf("attempting to deliver %s with maildir\n", msg->uid);
196 if(maildir_out(msg, hdr_list, rcpt->local_part, 0)){ 187 if (maildir_out(msg, hdr_list, rcpt->local_part, 0)) {
197 if(env_addr != rcpt){ 188 if (env_addr != rcpt) {
198 logwrite(LOG_NOTICE, "%s => %s@%s <%s@%s> with local\n", 189 logwrite(LOG_NOTICE, "%s => %s@%s <%s@%s> with local\n", msg->uid,
199 msg->uid, rcpt->local_part, rcpt->domain, 190 rcpt->local_part, rcpt->domain, env_addr->local_part, env_addr->domain);
200 env_addr->local_part, env_addr->domain 191 } else {
201 ); 192 logwrite(LOG_NOTICE, "%s => <%s@%s> with maildir\n", msg->uid,
202 }else{ 193 rcpt->local_part, rcpt->domain);
203 logwrite(LOG_NOTICE, "%s => <%s@%s> with maildir\n", 194 }
204 msg->uid, rcpt->local_part, rcpt->domain); 195 addr_mark_delivered(rcpt);
205 } 196 ok = TRUE;
206 addr_mark_delivered(rcpt); 197 } else
207 ok = TRUE; 198 addr_mark_failed(rcpt);
208 }else
209 addr_mark_failed(rcpt);
210 #endif 199 #endif
211 }else 200 } else
212 logwrite(LOG_ALERT, "unknown mbox type '%s'\n", mbox_type); 201 logwrite(LOG_ALERT, "unknown mbox type '%s'\n", mbox_type);
213 } 202 }
214 203
215 destroy_header(retpath_hdr); 204 destroy_header(retpath_hdr);
216 destroy_header(envto_hdr); 205 destroy_header(envto_hdr);
217 206
218 g_list_free(hdr_list); 207 g_list_free(hdr_list);
219 } 208 }
220 ok_fail = delivery_failures(msg, rcpt_list, "%s (%d)", ext_strerror(errno), errno); 209 ok_fail = delivery_failures(msg, rcpt_list, "%s (%d)", ext_strerror(errno), errno);
221 210
222 if(flag) msg_free_data(msg); 211 if (flag)
223 if(ok || ok_fail) deliver_finish(msgout); 212 msg_free_data(msg);
224 213 if (ok || ok_fail)
225 return ok; 214 deliver_finish(msgout);
215
216 return ok;
226 } 217 }
227 218
228 /* make a list of rcpt's of a message that are local 219 /* make a list of rcpt's of a message that are local
229 return a new copy of the list 220 return a new copy of the list
230 */ 221 */
231 void msg_rcptlist_local(GList *rcpt_list, GList **p_local_list, GList **p_nonlocal_list) 222 void
232 { 223 msg_rcptlist_local(GList * rcpt_list, GList ** p_local_list, GList ** p_nonlocal_list)
233 GList *rcpt_node; 224 {
234 225 GList *rcpt_node;
235 foreach(rcpt_list, rcpt_node){ 226
236 address *rcpt = (address *)(rcpt_node->data); 227 foreach(rcpt_list, rcpt_node) {
237 GList *dom_node; 228 address *rcpt = (address *) (rcpt_node->data);
238 229 GList *dom_node;
239 DEBUG(5) debugf("checking address %s\n", rcpt->address); 230
240 231 DEBUG(5) debugf("checking address %s\n", rcpt->address);
241 /* search for local host list: */ 232
242 foreach(conf.local_hosts, dom_node){ 233 /* search for local host list: */
243 if(strcasecmp(dom_node->data, rcpt->domain) == 0){ 234 foreach(conf.local_hosts, dom_node) {
244 *p_local_list = g_list_append(*p_local_list, rcpt); 235 if (strcasecmp(dom_node->data, rcpt->domain) == 0) {
245 DEBUG(5) debugf("<%s@%s> is local\n", rcpt->local_part, rcpt->domain); 236 *p_local_list = g_list_append(*p_local_list, rcpt);
246 break; 237 DEBUG(5) debugf("<%s@%s> is local\n", rcpt->local_part, rcpt->domain);
247 }else{ 238 break;
248 *p_nonlocal_list = g_list_append(*p_nonlocal_list, rcpt); 239 } else {
249 } 240 *p_nonlocal_list = g_list_append(*p_nonlocal_list, rcpt);
250 } 241 }
251 } 242 }
252 } 243 }
253 244 }
254 gboolean deliver_msglist_host_pipe(connect_route *route, GList *msgout_list, gchar *host, GList *res_list) 245
255 { 246 gboolean
256 gboolean ok = TRUE; 247 deliver_msglist_host_pipe(connect_route * route, GList * msgout_list, gchar * host, GList * res_list)
257 GList *msgout_node; 248 {
258 249 gboolean ok = TRUE;
259 DEBUG(5) debugf("deliver_msglist_host_pipe entered\n"); 250 GList *msgout_node;
260 251
261 if(route->pipe == NULL){ 252 DEBUG(5) debugf("deliver_msglist_host_pipe entered\n");
262 logwrite(LOG_ALERT, "no pipe command given for route (protocol is pipe!)\n"); 253
263 return FALSE; 254 if (route->pipe == NULL) {
264 } 255 logwrite(LOG_ALERT, "no pipe command given for route (protocol is pipe!)\n");
265 256 return FALSE;
266 foreach(msgout_list, msgout_node){ 257 }
267 msg_out *msgout = (msg_out *)(msgout_node->data); 258
268 gboolean flag, ok_msg = TRUE, ok_fail = FALSE; 259 foreach(msgout_list, msgout_node) {
269 message *msg = msgout->msg; 260 msg_out *msgout = (msg_out *) (msgout_node->data);
270 GList *rcpt_node, *rcpt_list = msgout->rcpt_list; 261 gboolean flag, ok_msg = TRUE, ok_fail = FALSE;
271 262 message *msg = msgout->msg;
272 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid); 263 GList *rcpt_node, *rcpt_list = msgout->rcpt_list;
273 264
274 flag = (msg->data_list == NULL); 265 DEBUG(1) debugf("attempting to deliver %s with pipe\n", msg->uid);
275 if(flag){ 266
276 if(!(ok_msg = spool_read_data(msg))){ 267 flag = (msg->data_list == NULL);
277 logwrite(LOG_ALERT, "could not open data spool file for %s\n", 268 if (flag) {
278 msg->uid); 269 if (!(ok_msg = spool_read_data(msg))) {
279 } 270 logwrite(LOG_ALERT, "could not open data spool file for %s\n", msg->uid);
280 } 271 }
281 if(!ok_msg) continue; 272 }
282 273 if (!ok_msg)
283 ok = FALSE; 274 continue;
284 foreach(rcpt_list, rcpt_node){ 275
285 address *rcpt = (address *)(rcpt_node->data); 276 ok = FALSE;
286 gchar *cmd = g_malloc(256); 277 foreach(rcpt_list, rcpt_node) {
287 GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt); 278 address *rcpt = (address *) (rcpt_node->data);
288 279 gchar *cmd = g_malloc(256);
289 DEBUG(1) debugf("attempting to deliver %s to %s@%s with pipe\n", 280 GList *var_table = var_table_rcpt(var_table_msg(NULL, msg), rcpt);
290 msg->uid, rcpt->local_part, rcpt->domain); 281
291 282 DEBUG(1) debugf("attempting to deliver %s to %s@%s with pipe\n", msg->uid, rcpt->local_part, rcpt->domain);
292 if(expand(var_table, route->pipe, cmd, 256)){ 283
293 284 if (expand(var_table, route->pipe, cmd, 256)) {
294 if(pipe_out(msg, msg->hdr_list, rcpt, cmd, 285
295 (route->pipe_fromline ? MSGSTR_FROMLINE : 0) | 286 if (pipe_out(msg, msg->hdr_list, rcpt, cmd, (route->pipe_fromline ? MSGSTR_FROMLINE : 0)
296 (route->pipe_fromhack ? MSGSTR_FROMHACK : 0))){ 287 | (route->pipe_fromhack ? MSGSTR_FROMHACK : 0))) {
297 logwrite(LOG_NOTICE, "%s => %s@%s with pipe (cmd = '%s')\n", 288 logwrite(LOG_NOTICE, "%s => %s@%s with pipe (cmd = '%s')\n",
298 msg->uid, rcpt->local_part, rcpt->domain, cmd 289 msg->uid, rcpt->local_part, rcpt->domain, cmd);
299 ); 290 addr_mark_delivered(rcpt);
300 addr_mark_delivered(rcpt); 291 ok = TRUE;
301 ok = TRUE; 292 } else {
302 }else{ 293 logwrite(LOG_ALERT, "pipe_out '%s' failed\n", route->pipe);
303 logwrite(LOG_ALERT, "pipe_out '%s' failed\n", route->pipe); 294
304 295 if (route->connect_error_fail) {
305 if(route->connect_error_fail){ 296 addr_mark_failed(rcpt);
306 addr_mark_failed(rcpt); 297 } else {
307 }else{ 298 addr_mark_defered(rcpt);
308 addr_mark_defered(rcpt); 299 }
309 } 300 }
310 } 301 } else
311 }else 302 logwrite(LOG_ALERT, "could not expand string %s\n", route->pipe);
312 logwrite(LOG_ALERT, "could not expand string %s\n", route->pipe); 303
313 304 destroy_table(var_table);
314 destroy_table(var_table); 305 }
315 } 306 ok_fail = delivery_failures(msg, rcpt_list, "%s", strerror(errno));
316 ok_fail = delivery_failures(msg, rcpt_list, "%s", strerror(errno)); 307
317 308 if (flag)
318 if(flag) msg_free_data(msg); 309 msg_free_data(msg);
319 310
320 if(ok || ok_fail) deliver_finish(msgout); 311 if (ok || ok_fail)
321 } 312 deliver_finish(msgout);
322 313 }
323 return ok; 314
315 return ok;
324 } 316 }
325 317
326 /* deliver list of messages to one host 318 /* deliver list of messages to one host
327 and finishes them if the message was delivered to at least one 319 and finishes them if the message was delivered to at least one rcpt.
328 rcpt. 320 Returns TRUE if at least one msg was delivered to at least one rcpt.
329 Returns TRUE if at least one msg was delivered to at least one
330 rcpt.
331 */ 321 */
332 322
333 gboolean deliver_msglist_host_smtp(connect_route *route, GList *msgout_list, gchar *host, GList *res_list) 323 gboolean
334 { 324 deliver_msglist_host_smtp(connect_route * route, GList * msgout_list, gchar * host, GList * res_list)
335 gboolean ok = FALSE; 325 {
336 GList *msgout_node; 326 gboolean ok = FALSE;
337 smtp_base *psb; 327 GList *msgout_node;
338 gint port; 328 smtp_base *psb;
339 329 gint port;
340 /* paranoid check: */ 330
341 if(msgout_list == NULL){ 331 /* paranoid check: */
342 logwrite(LOG_ALERT, 332 if (msgout_list == NULL) {
343 "Ooops: empty list of messages in deliver_msglist_host()\n"); 333 logwrite(LOG_ALERT, "Ooops: empty list of messages in deliver_msglist_host()\n");
344 return FALSE; 334 return FALSE;
345 } 335 }
346 336
347 if(host == NULL){ 337 if (host == NULL) {
348 host = route->mail_host->address; 338 host = route->mail_host->address;
349 port = route->mail_host->port; 339 port = route->mail_host->port;
350 }else 340 } else
351 port = conf.remote_port; 341 port = conf.remote_port;
352 342
353 #ifdef ENABLE_POP3 343 #ifdef ENABLE_POP3
354 if(route->pop3_login){ 344 if (route->pop3_login) {
355 if(!(pop_before_smtp(route->pop3_login))) 345 if (!(pop_before_smtp(route->pop3_login)))
356 return FALSE; 346 return FALSE;
357 } 347 }
358 #endif 348 #endif
359 349
360 if((psb = (route->wrapper ? 350 if ((psb = (route->wrapper ? smtp_out_open_child(route->wrapper) : smtp_out_open(host, port, res_list)))) {
361 smtp_out_open_child(route->wrapper) : 351
362 smtp_out_open(host, port, res_list)))){ 352 if (route->wrapper)
363 353 psb->remote_host = host;
364 if(route->wrapper) psb->remote_host = host; 354
365 355 set_heloname(psb, route->helo_name ? route->helo_name : conf.host_name, route->do_correct_helo);
366 set_heloname(psb,
367 route->helo_name ? route->helo_name : conf.host_name,
368 route->do_correct_helo);
369 356
370 #ifdef ENABLE_AUTH 357 #ifdef ENABLE_AUTH
371 if((route->auth_name) && (route->auth_login) && (route->auth_secret)) 358 if ((route->auth_name) && (route->auth_login)
372 set_auth(psb, route->auth_name, route->auth_login, route->auth_secret); 359 && (route->auth_secret))
360 set_auth(psb, route->auth_name, route->auth_login, route->auth_secret);
373 #endif 361 #endif
374 if(smtp_out_init(psb)){ 362 if (smtp_out_init(psb)) {
375 363
376 if(!route->do_pipelining) psb->use_pipelining = FALSE; 364 if (!route->do_pipelining)
377 365 psb->use_pipelining = FALSE;
378 foreach(msgout_list, msgout_node){ 366
379 msg_out *msgout = (msg_out *)(msgout_node->data); 367 foreach(msgout_list, msgout_node) {
380 gboolean flag, ok_msg = FALSE, ok_fail = FALSE; 368 msg_out *msgout = (msg_out *) (msgout_node->data);
381 message *msg = msgout->msg; 369 gboolean flag, ok_msg = FALSE, ok_fail = FALSE;
382 370 message *msg = msgout->msg;
383 /* we may have to read the data at this point 371
384 and remember if we did */ 372 /* we may have to read the data at this point
385 flag = (msg->data_list == NULL); 373 and remember if we did */
386 if(flag){ 374 flag = (msg->data_list == NULL);
387 if(!spool_read_data(msg)){ 375 if (flag) {
388 logwrite(LOG_ALERT, "could not open data spool file %s\n", 376 if (!spool_read_data(msg)) {
389 msg->uid); 377 logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid);
390 break; 378 break;
391 } 379 }
392 } 380 }
393 381
394 smtp_out_msg(psb, msg, 382 smtp_out_msg(psb, msg, msgout->return_path, msgout->rcpt_list, msgout->hdr_list);
395 msgout->return_path, msgout->rcpt_list, msgout->hdr_list); 383
396 384 ok_fail = delivery_failures(msg, msgout->rcpt_list, "while connected with %s, the server replied\n\t%s", host, psb->buffer);
397 ok_fail = delivery_failures(msg, msgout->rcpt_list, 385
398 "while connected with %s, the server replied\n\t%s", 386 if ((psb->error == smtp_eof)
399 host, psb->buffer); 387 || (psb->error == smtp_timeout)) {
400 388 /* connection lost */
401 if((psb->error == smtp_eof) || 389 break;
402 (psb->error == smtp_timeout)){ 390 } else if (psb->error != smtp_ok) {
403 /* connection lost */ 391 if (g_list_next(msgout_node) != NULL)
404 break; 392 if (!smtp_out_rset(psb))
405 } 393 break;
406 else if(psb->error != smtp_ok){ 394 }
407 if(g_list_next(msgout_node) != NULL) 395 ok_msg = (psb->error == smtp_ok);
408 if(!smtp_out_rset(psb)) 396
409 break; 397 if (flag)
410 } 398 msg_free_data(msg);
411 ok_msg = (psb->error == smtp_ok); 399 if (ok_msg)
412 400 ok = TRUE;
413 if(flag) msg_free_data(msg); 401 if (ok_msg || ok_fail) {
414 if(ok_msg) ok = TRUE; 402 deliver_finish(msgout);
415 if(ok_msg || ok_fail){ 403 }
416 deliver_finish(msgout); 404 }
417 } 405 if (psb->error == smtp_ok || (psb->error == smtp_fail)
418 } 406 || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) {
419 if(psb->error == smtp_ok || 407 smtp_out_quit(psb);
420 (psb->error == smtp_fail) || 408 }
421 (psb->error == smtp_trylater) || 409 } else {
422 (psb->error == smtp_syntax)){ 410 /* smtp_out_init() failed */
423 411 if ((psb->error == smtp_fail) || (psb->error == smtp_trylater) || (psb->error == smtp_syntax)) {
424 smtp_out_quit(psb); 412 smtp_out_quit(psb);
425 } 413
426 }else{ 414 foreach(msgout_list, msgout_node) {
427 /* smtp_out_init() failed */ 415 msg_out *msgout = (msg_out *) (msgout_node->data);
428 if((psb->error == smtp_fail) || 416 smtp_out_mark_rcpts(psb, msgout->rcpt_list);
429 (psb->error == smtp_trylater) || 417
430 (psb->error == smtp_syntax)){ 418 if (delivery_failures(msgout->msg, msgout->rcpt_list,
431 smtp_out_quit(psb); 419 "while connected with %s, the server replied\n\t%s", host, psb->buffer))
432 420 deliver_finish(msgout);
433 foreach(msgout_list, msgout_node){ 421 }
434 msg_out *msgout = (msg_out *)(msgout_node->data); 422 }
435 smtp_out_mark_rcpts(psb, msgout->rcpt_list); 423 }
436 424 destroy_smtpbase(psb);
437 if(delivery_failures(msgout->msg, msgout->rcpt_list, 425 } else {
438 "while connected with %s, the server replied\n\t%s", 426 /* smtp_out_open() failed */
439 host, psb->buffer)) 427 foreach(msgout_list, msgout_node) {
440 deliver_finish(msgout); 428 msg_out *msgout = (msg_out *) (msgout_node->data);
441 } 429 GList *rcpt_node;
442 } 430
443 } 431 for (rcpt_node = g_list_first(msgout->rcpt_list); rcpt_node; rcpt_node = g_list_next(rcpt_node)) {
444 destroy_smtpbase(psb); 432 address *rcpt = (address *) (rcpt_node->data);
445 }else{ 433
446 /* smtp_out_open() failed */ 434 addr_unmark_delivered(rcpt);
447 foreach(msgout_list, msgout_node){ 435 if (route->connect_error_fail) {
448 msg_out *msgout = (msg_out *)(msgout_node->data); 436 addr_mark_failed(rcpt);
449 GList *rcpt_node; 437 } else {
450 438 addr_mark_defered(rcpt);
451 for(rcpt_node = g_list_first(msgout->rcpt_list); 439 }
452 rcpt_node; 440 if (route->wrapper
453 rcpt_node = g_list_next(rcpt_node)){ 441 ? delivery_failures(msgout->msg, msgout->rcpt_list,
454 address *rcpt = (address *)(rcpt_node->data); 442 "could not open wrapper:\n\t%s",
455 443 strerror(errno))
456 addr_unmark_delivered(rcpt); 444 : delivery_failures(msgout->msg, msgout->rcpt_list,
457 if(route->connect_error_fail){ 445 "could not open connection to %s:%d :\n\t%s",
458 addr_mark_failed(rcpt); 446 host, port, h_errno != 0 ? hstrerror(h_errno) : strerror(errno)))
459 }else{ 447 deliver_finish(msgout);
460 addr_mark_defered(rcpt); 448 }
461 } 449 }
462 if(route->wrapper ? 450 }
463 delivery_failures(msgout->msg, msgout->rcpt_list, 451 return ok;
464 "could not open wrapper:\n\t%s", 452 }
465 strerror(errno)) : 453
466 delivery_failures(msgout->msg, msgout->rcpt_list, 454 gboolean
467 "could not open connection to %s:%d :\n\t%s", 455 deliver_msglist_host(connect_route * route, GList * msgout_list, gchar * host, GList * res_list)
468 host, port, h_errno != 0 ? hstrerror(h_errno) : strerror(errno))) 456 {
469 deliver_finish(msgout); 457 DEBUG(5) debugf("protocol = %s\n", route->protocol);
470 } 458
471 } 459 if (strcmp(route->protocol, "pipe") == 0) {
472 } 460 return deliver_msglist_host_pipe(route, msgout_list, host, res_list);
473 return ok; 461 } else {
474 } 462 return deliver_msglist_host_smtp(route, msgout_list, host, res_list);
475 463 }
476 gboolean deliver_msglist_host(connect_route *route, GList *msgout_list, gchar *host, GList *res_list)
477 {
478 DEBUG(5) debugf("protocol = %s\n", route->protocol);
479
480 if(strcmp(route->protocol, "pipe") == 0){
481 return deliver_msglist_host_pipe(route, msgout_list, host, res_list);
482 }else{
483 return deliver_msglist_host_smtp(route, msgout_list, host, res_list);
484 }
485 } 464 }
486 465
487 /* 466 /*
488 delivers messages in msgout_list using route 467 delivers messages in msgout_list using route
489 */ 468 */
490 gboolean deliver_route_msgout_list(connect_route *route, GList *msgout_list) 469 gboolean
491 { 470 deliver_route_msgout_list(connect_route * route, GList * msgout_list)
492 gboolean ok = FALSE; 471 {
493 472 gboolean ok = FALSE;
494 DEBUG(5) debugf("deliver_route_msgout_list entered, route->name = %s\n", 473
495 route->name); 474 DEBUG(5)
496 475 debugf("deliver_route_msgout_list entered, route->name = %s\n", route->name);
497 if(route->mail_host != NULL){ 476
498 /* this is easy... */ 477 if (route->mail_host != NULL) {
499 if(deliver_msglist_host(route, msgout_list, 478 /* this is easy... */
500 NULL, route->resolve_list)) 479 if (deliver_msglist_host(route, msgout_list, NULL, route->resolve_list))
501 ok = TRUE; 480 ok = TRUE;
502 481
503 }else{ 482 } else {
504 /* this is not easy... */ 483 /* this is not easy... */
505 GList *mo_ph_list; 484 GList *mo_ph_list;
506 485
507 mo_ph_list = route_msgout_list(route, msgout_list); 486 mo_ph_list = route_msgout_list(route, msgout_list);
508 /* okay, now we have ordered our messages by the hosts. */ 487 /* okay, now we have ordered our messages by the hosts. */
509 if(mo_ph_list != NULL){ 488 if (mo_ph_list != NULL) {
510 GList *mo_ph_node; 489 GList *mo_ph_node;
511 /* TODO: It would be nice to be able to fork for each host. 490 /* TODO: It would be nice to be able to fork for each host.
512 We cannot do that yet because of complications with finishing the 491 We cannot do that yet because of complications with finishing the
513 messages. Threads could be a solution because they use the same 492 messages. Threads could be a solution because they use the same
514 memory. But we are not thread safe yet... 493 memory. But we are not thread safe yet...
515 */ 494 */
516 foreach(mo_ph_list, mo_ph_node){ 495 foreach(mo_ph_list, mo_ph_node) {
517 msgout_perhost *mo_ph = (msgout_perhost *)(mo_ph_node->data); 496 msgout_perhost *mo_ph = (msgout_perhost *) (mo_ph_node->data);
518 if(deliver_msglist_host(route, mo_ph->msgout_list, 497 if (deliver_msglist_host (route, mo_ph->msgout_list, mo_ph->host, route->resolve_list))
519 mo_ph->host, route->resolve_list)) 498 ok = TRUE;
520 ok = TRUE; 499
521 500 destroy_msgout_perhost(mo_ph);
522 destroy_msgout_perhost(mo_ph); 501 }
523 } 502 g_list_free(mo_ph_list);
524 g_list_free(mo_ph_list); 503 }
525 } 504 }
526 } 505 return ok;
527 return ok;
528 } 506 }
529 507
530 /* 508 /*
531 calls route_prepare_msg() 509 calls route_prepare_msg()
532 delivers messages in msg_list using route 510 delivers messages in msg_list using route
533 by calling deliver_route_msgout_list() 511 by calling deliver_route_msgout_list()
534 */ 512 */
535 gboolean deliver_route_msg_list(connect_route *route, GList *msgout_list) 513 gboolean
536 { 514 deliver_route_msg_list(connect_route * route, GList * msgout_list)
537 GList *msgout_list_deliver = NULL; 515 {
538 GList *msgout_node; 516 GList *msgout_list_deliver = NULL;
539 gboolean ok = TRUE; 517 GList *msgout_node;
540 518 gboolean ok = TRUE;
541 DEBUG(6) debugf("deliver_route_msg_list()\n"); 519
542 520 DEBUG(6) debugf("deliver_route_msg_list()\n");
543 foreach(msgout_list, msgout_node){ 521
544 msg_out *msgout = (msg_out *)(msgout_node->data); 522 foreach(msgout_list, msgout_node) {
545 msg_out *msgout_cloned = clone_msg_out(msgout); 523 msg_out *msgout = (msg_out *) (msgout_node->data);
546 GList *rcpt_list_non_delivered = NULL; 524 msg_out *msgout_cloned = clone_msg_out(msgout);
547 GList *rcpt_node; 525 GList *rcpt_list_non_delivered = NULL;
548 526 GList *rcpt_node;
549 /* we have to delete already delivered rcpt's 527
550 because a previous route may have delivered to it */ 528 /* we have to delete already delivered rcpt's
551 foreach(msgout_cloned->rcpt_list, rcpt_node){ 529 because a previous route may have delivered to it */
552 address *rcpt = (address *)(rcpt_node->data); 530 foreach(msgout_cloned->rcpt_list, rcpt_node) {
553 /* failed addresses already have been bounced 531 address *rcpt = (address *) (rcpt_node->data);
554 - there should be a better way to handle those.*/ 532 /* failed addresses already have been bounced
555 if(!addr_is_delivered(rcpt) && !addr_is_failed(rcpt) && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE)) 533 - there should be a better way to handle those. */
556 rcpt_list_non_delivered = g_list_append(rcpt_list_non_delivered, rcpt); 534 if (!addr_is_delivered(rcpt) && !addr_is_failed(rcpt)
557 } 535 && !(rcpt->flags & ADDR_FLAG_LAST_ROUTE))
558 g_list_free(msgout_cloned->rcpt_list); 536 rcpt_list_non_delivered = g_list_append(rcpt_list_non_delivered, rcpt);
559 msgout_cloned->rcpt_list = rcpt_list_non_delivered; 537 }
560 538 g_list_free(msgout_cloned->rcpt_list);
561 if(msgout_cloned->rcpt_list){ 539 msgout_cloned->rcpt_list = rcpt_list_non_delivered;
562 if(route_is_allowed_mail_local(route, msgout->msg->return_path) && 540
563 route_is_allowed_return_path(route, msgout->msg->return_path)){ 541 if (msgout_cloned->rcpt_list) {
564 GList *rcpt_list_allowed = NULL, *rcpt_list_notallowed = NULL; 542 if (route_is_allowed_mail_local(route, msgout->msg->return_path)
565 msg_rcptlist_route(route, msgout_cloned->rcpt_list, 543 && route_is_allowed_return_path(route, msgout->msg-> return_path)) {
566 &rcpt_list_allowed, &rcpt_list_notallowed); 544 GList *rcpt_list_allowed = NULL, *rcpt_list_notallowed = NULL;
567 545 msg_rcptlist_route(route, msgout_cloned->rcpt_list, &rcpt_list_allowed, &rcpt_list_notallowed);
568 if(rcpt_list_allowed != NULL){ 546
569 logwrite(LOG_NOTICE, "%s using '%s'\n", msgout->msg->uid, route->name); 547 if (rcpt_list_allowed != NULL) {
570 548 logwrite(LOG_NOTICE, "%s using '%s'\n", msgout->msg->uid, route->name);
571 g_list_free(msgout_cloned->rcpt_list); 549
572 msgout_cloned->rcpt_list = rcpt_list_allowed; 550 g_list_free(msgout_cloned->rcpt_list);
573 551 msgout_cloned->rcpt_list = rcpt_list_allowed;
574 if(route->last_route){ 552
575 GList *rcpt_node; 553 if (route->last_route) {
576 foreach(msgout_cloned->rcpt_list, rcpt_node){ 554 GList *rcpt_node;
577 address *rcpt = (address *)(rcpt_node->data); 555 foreach(msgout_cloned->rcpt_list, rcpt_node) {
578 rcpt->flags |= ADDR_FLAG_LAST_ROUTE; 556 address *rcpt = (address *) (rcpt_node->data);
579 } 557 rcpt->flags |= ADDR_FLAG_LAST_ROUTE;
580 } 558 }
581 559 }
582 route_prepare_msgout(route, msgout_cloned); 560
583 msgout_list_deliver = g_list_append(msgout_list_deliver, msgout_cloned); 561 route_prepare_msgout(route, msgout_cloned);
584 }else 562 msgout_list_deliver = g_list_append(msgout_list_deliver, msgout_cloned);
585 destroy_msg_out(msgout_cloned); 563 } else
586 } 564 destroy_msg_out(msgout_cloned);
587 else 565 } else
588 destroy_msg_out(msgout_cloned); 566 destroy_msg_out(msgout_cloned);
589 }else 567 } else
590 destroy_msg_out(msgout_cloned); 568 destroy_msg_out(msgout_cloned);
591 } 569 }
592 570
593 if(msgout_list_deliver != NULL){ 571 if (msgout_list_deliver != NULL) {
594 if(deliver_route_msgout_list(route, msgout_list_deliver)) 572 if (deliver_route_msgout_list(route, msgout_list_deliver))
595 ok = TRUE; 573 ok = TRUE;
596 destroy_msg_out_list(msgout_list_deliver); 574 destroy_msg_out_list(msgout_list_deliver);
597 } 575 }
598 return ok; 576 return ok;
599 } 577 }
600 578
601 /* copy pointers of delivered addresses to the msg's non_rcpt_list, 579 /* copy pointers of delivered addresses to the msg's non_rcpt_list,
602 to make sure that they will not be delivered again. 580 to make sure that they will not be delivered again.
603 */ 581 */
604 void update_non_rcpt_list(msg_out *msgout) 582 void
605 { 583 update_non_rcpt_list(msg_out * msgout)
606 GList *rcpt_node; 584 {
607 message *msg = msgout->msg; 585 GList *rcpt_node;
608 586 message *msg = msgout->msg;
609 foreach(msgout->rcpt_list, rcpt_node){ 587
610 address *rcpt = (address *)(rcpt_node->data); 588 foreach(msgout->rcpt_list, rcpt_node) {
611 if(addr_is_delivered(rcpt) || addr_is_failed(rcpt)) 589 address *rcpt = (address *) (rcpt_node->data);
612 msg->non_rcpt_list = g_list_append(msg->non_rcpt_list, rcpt); 590 if (addr_is_delivered(rcpt) || addr_is_failed(rcpt))
613 } 591 msg->non_rcpt_list = g_list_append(msg->non_rcpt_list, rcpt);
592 }
614 } 593 }
615 594
616 /* after delivery attempts, we check if there are any 595 /* after delivery attempts, we check if there are any
617 rcpt addresses left in the message. 596 rcpt addresses left in the message.
618 If all addresses have been completed, the spool files will 597 If all addresses have been completed, the spool files will
619 be deleted, otherwise the header spool will be written back. 598 be deleted, otherwise the header spool will be written back.
620 We never changed the data spool, so there is no need to write that back. 599 We never changed the data spool, so there is no need to write that back.
621 600
622 returns TRUE if all went well. 601 returns TRUE if all went well.
623 */ 602 */
624 gboolean deliver_finish(msg_out *msgout) 603 gboolean
625 { 604 deliver_finish(msg_out * msgout)
626 GList *rcpt_node; 605 {
627 gboolean ok = FALSE; 606 GList *rcpt_node;
628 message *msg = msgout->msg; 607 gboolean ok = FALSE;
629 gboolean finished = TRUE; 608 message *msg = msgout->msg;
630 609 gboolean finished = TRUE;
631 update_non_rcpt_list(msgout); 610
632 611 update_non_rcpt_list(msgout);
633 /* we NEVER made copies of the addresses, flags affecting addresses 612
634 were always set on the original address structs */ 613 /* we NEVER made copies of the addresses, flags affecting addresses
635 foreach(msg->rcpt_list, rcpt_node){ 614 were always set on the original address structs */
636 address *rcpt = (address *)(rcpt_node->data); 615 foreach(msg->rcpt_list, rcpt_node) {
637 if(!addr_is_finished_children(rcpt)) 616 address *rcpt = (address *) (rcpt_node->data);
638 finished = FALSE; 617 if (!addr_is_finished_children(rcpt))
639 else{ 618 finished = FALSE;
640 /* if ALL children have been delivered, 619 else {
641 mark parent as delivered. 620 /* if ALL children have been delivered,
642 if there is one or more not delivered, 621 mark parent as delivered.
643 it must have failed, we mark the parent as failed as well. 622 if there is one or more not delivered,
644 */ 623 it must have failed, we mark the parent as failed as well.
645 if(addr_is_delivered_children(rcpt)){ 624 */
646 addr_mark_delivered(rcpt); 625 if (addr_is_delivered_children(rcpt)) {
647 }else{ 626 addr_mark_delivered(rcpt);
648 addr_mark_failed(rcpt); 627 } else {
649 } 628 addr_mark_failed(rcpt);
650 } 629 }
651 } 630 }
652 631 }
653 if(!finished){ 632
654 /* one not delivered address was found */ 633 if (!finished) {
655 if(spool_write(msg, FALSE)){ 634 /* one not delivered address was found */
656 ok = TRUE; 635 if (spool_write(msg, FALSE)) {
657 DEBUG(2) debugf("spool header for %s written back.\n", msg->uid); 636 ok = TRUE;
658 }else 637 DEBUG(2) debugf("spool header for %s written back.\n", msg->uid);
659 logwrite(LOG_ALERT, "could not write back spool header for %s\n", 638 } else
660 msg->uid); 639 logwrite(LOG_ALERT, "could not write back spool header for %s\n", msg->uid);
661 }else{ 640 } else {
662 ok = spool_delete_all(msg); 641 ok = spool_delete_all(msg);
663 if(ok) 642 if (ok)
664 logwrite(LOG_NOTICE, "%s completed.\n", msg->uid); 643 logwrite(LOG_NOTICE, "%s completed.\n", msg->uid);
665 } 644 }
666 return ok; 645 return ok;
667 } 646 }
668 647
669 gboolean deliver_finish_list(GList *msgout_list) 648 gboolean
670 { 649 deliver_finish_list(GList * msgout_list)
671 gboolean ok = TRUE; 650 {
672 GList *msgout_node; 651 gboolean ok = TRUE;
673 foreach(msgout_list, msgout_node){ 652 GList *msgout_node;
674 msg_out *msgout = (msg_out *)(msgout_node->data); 653 foreach(msgout_list, msgout_node) {
675 if(!deliver_finish(msgout)) 654 msg_out *msgout = (msg_out *) (msgout_node->data);
676 ok = FALSE; 655 if (!deliver_finish(msgout))
677 } 656 ok = FALSE;
678 return ok; 657 }
679 } 658 return ok;
680 659 }
681 gboolean deliver_msgout_list_online(GList *msgout_list) 660
682 { 661 gboolean
683 GList *rf_list = NULL; 662 deliver_msgout_list_online(GList * msgout_list)
684 gchar *connect_name = detect_online(); 663 {
685 gboolean ok = FALSE; 664 GList *rf_list = NULL;
686 665 gchar *connect_name = detect_online();
687 if(connect_name != NULL){ 666 gboolean ok = FALSE;
688 logwrite(LOG_NOTICE, "detected online configuration %s\n", connect_name); 667
689 /* we are online! */ 668 if (connect_name != NULL) {
690 rf_list = (GList *)table_find(conf.connect_routes, connect_name); 669 logwrite(LOG_NOTICE, "detected online configuration %s\n", connect_name);
691 if(rf_list != NULL){ 670 /* we are online! */
692 GList *route_list = read_route_list(rf_list, FALSE); 671 rf_list = (GList *) table_find(conf.connect_routes, connect_name);
693 if(route_list){ 672 if (rf_list != NULL) {
694 GList *route_node; 673 GList *route_list = read_route_list(rf_list, FALSE);
695 foreach(route_list, route_node){ 674 if (route_list) {
696 connect_route *route = (connect_route *)(route_node->data); 675 GList *route_node;
697 ok = deliver_route_msg_list(route, msgout_list); 676 foreach(route_list, route_node) {
698 } 677 connect_route *route = (connect_route *) (route_node->data);
699 destroy_route_list(route_list); 678 ok = deliver_route_msg_list(route, msgout_list);
700 } 679 }
701 else 680 destroy_route_list(route_list);
702 logwrite(LOG_ALERT, 681 } else
703 "could not read route list '%s'\n", connect_name); 682 logwrite(LOG_ALERT, "could not read route list '%s'\n", connect_name);
704 }else{ 683 } else {
705 logwrite(LOG_ALERT, "route list with name '%s' not found.\n", connect_name); 684 logwrite(LOG_ALERT, "route list with name '%s' not found.\n", connect_name);
706 } 685 }
707 } 686 }
708 return ok; 687 return ok;
709 } 688 }
710 689
711 gboolean deliver_msg_list(GList *msg_list, guint flags){ 690 gboolean
712 GList *msgout_list = create_msg_out_list(msg_list); 691 deliver_msg_list(GList * msg_list, guint flags)
713 GList *local_msgout_list = NULL, *localnet_msgout_list = NULL, *other_msgout_list = NULL; 692 {
714 GList *msgout_node; 693 GList *msgout_list = create_msg_out_list(msg_list);
715 GList *alias_table = NULL; 694 GList *local_msgout_list = NULL, *localnet_msgout_list = NULL, *other_msgout_list = NULL;
716 gboolean ok = TRUE; 695 GList *msgout_node;
717 696 GList *alias_table = NULL;
718 if(conf.alias_file){ 697 gboolean ok = TRUE;
719 if(!(alias_table = table_read(conf.alias_file, ':'))) 698
720 return FALSE; 699 if (conf.alias_file) {
721 } 700 if (!(alias_table = table_read(conf.alias_file, ':')))
722 701 return FALSE;
723 /* sort messages for different deliveries */ 702 }
724 foreach(msgout_list, msgout_node){ 703
725 msg_out *msgout = (msg_out *)(msgout_node->data); 704 /* sort messages for different deliveries */
726 GList *rcpt_list; 705 foreach(msgout_list, msgout_node) {
727 GList *local_rcpt_list = NULL; 706 msg_out *msgout = (msg_out *) (msgout_node->data);
728 GList *localnet_rcpt_list = NULL; 707 GList *rcpt_list;
729 GList *other_rcpt_list; 708 GList *local_rcpt_list = NULL;
730 709 GList *localnet_rcpt_list = NULL;
731 if(!spool_lock(msgout->msg->uid)) continue; 710 GList *other_rcpt_list;
732 711
733 rcpt_list = g_list_copy(msgout->msg->rcpt_list); 712 if (!spool_lock(msgout->msg->uid))
734 if(conf.log_user){ 713 continue;
735 address *addr = create_address_qualified(conf.log_user, TRUE, conf.host_name); 714
736 if(addr) 715 rcpt_list = g_list_copy(msgout->msg->rcpt_list);
737 rcpt_list = g_list_prepend(rcpt_list, addr); 716 if (conf.log_user) {
738 } 717 address *addr = create_address_qualified(conf.log_user, TRUE, conf.host_name);
739 if(alias_table){ 718 if (addr)
740 GList *aliased_rcpt_list; 719 rcpt_list = g_list_prepend(rcpt_list, addr);
741 aliased_rcpt_list = alias_expand(alias_table, rcpt_list, 720 }
742 msgout->msg->non_rcpt_list); 721 if (alias_table) {
743 g_list_free(rcpt_list); 722 GList *aliased_rcpt_list;
744 rcpt_list = aliased_rcpt_list; 723 aliased_rcpt_list = alias_expand(alias_table, rcpt_list, msgout->msg->non_rcpt_list);
745 } 724 g_list_free(rcpt_list);
746 725 rcpt_list = aliased_rcpt_list;
747 /* local recipients */ 726 }
748 other_rcpt_list = NULL; 727
749 rcptlist_with_addr_is_local(rcpt_list, &local_rcpt_list, &other_rcpt_list); 728 /* local recipients */
750 729 other_rcpt_list = NULL;
751 if(flags & DLVR_LOCAL){ 730 rcptlist_with_addr_is_local(rcpt_list, &local_rcpt_list, &other_rcpt_list);
752 if(local_rcpt_list != NULL){ 731
753 msg_out *local_msgout = clone_msg_out(msgout); 732 if (flags & DLVR_LOCAL) {
754 local_msgout->rcpt_list = local_rcpt_list; 733 if (local_rcpt_list != NULL) {
755 local_msgout_list = g_list_append(local_msgout_list, local_msgout); 734 msg_out *local_msgout = clone_msg_out(msgout);
756 } 735 local_msgout->rcpt_list = local_rcpt_list;
757 } 736 local_msgout_list = g_list_append(local_msgout_list, local_msgout);
758 737 }
759 g_list_free(rcpt_list); 738 }
760 739
761 /* local net recipients */ 740 g_list_free(rcpt_list);
762 rcpt_list = other_rcpt_list; 741
763 other_rcpt_list = NULL; 742 /* local net recipients */
764 rcptlist_with_one_of_hostlist(rcpt_list, conf.local_nets, 743 rcpt_list = other_rcpt_list;
765 &localnet_rcpt_list, &other_rcpt_list); 744 other_rcpt_list = NULL;
766 745 rcptlist_with_one_of_hostlist(rcpt_list, conf.local_nets, &localnet_rcpt_list, &other_rcpt_list);
767 if(flags & DLVR_LAN){ 746
768 if(localnet_rcpt_list != NULL){ 747 if (flags & DLVR_LAN) {
769 msg_out *localnet_msgout = clone_msg_out(msgout); 748 if (localnet_rcpt_list != NULL) {
770 localnet_msgout->rcpt_list = localnet_rcpt_list; 749 msg_out *localnet_msgout = clone_msg_out(msgout);
771 localnet_msgout_list = g_list_append(localnet_msgout_list, localnet_msgout); 750 localnet_msgout->rcpt_list = localnet_rcpt_list;
772 } 751 localnet_msgout_list = g_list_append(localnet_msgout_list, localnet_msgout);
773 } 752 }
774 753 }
775 if(flags & DLVR_ONLINE){ 754
776 /* the rest, this is online delivery */ 755 if (flags & DLVR_ONLINE) {
777 if(other_rcpt_list != NULL){ 756 /* the rest, this is online delivery */
778 msg_out *other_msgout = clone_msg_out(msgout); 757 if (other_rcpt_list != NULL) {
779 other_msgout->rcpt_list = other_rcpt_list; 758 msg_out *other_msgout = clone_msg_out(msgout);
780 other_msgout_list = g_list_append(other_msgout_list, other_msgout); 759 other_msgout->rcpt_list = other_rcpt_list;
781 } 760 other_msgout_list = g_list_append(other_msgout_list, other_msgout);
782 } 761 }
783 } 762 }
784 763 }
785 if(alias_table) 764
786 destroy_table(alias_table); 765 if (alias_table)
787 766 destroy_table(alias_table);
788 /* actual delivery */ 767
789 if(local_msgout_list != NULL){ 768 /* actual delivery */
790 foreach(local_msgout_list, msgout_node){ 769 if (local_msgout_list != NULL) {
791 msg_out *msgout = (msg_out *)(msgout_node->data); 770 foreach(local_msgout_list, msgout_node) {
792 if(!deliver_local(msgout)) ok = FALSE; 771 msg_out *msgout = (msg_out *) (msgout_node->data);
793 } 772 if (!deliver_local(msgout))
794 destroy_msg_out_list(local_msgout_list); 773 ok = FALSE;
795 } 774 }
796 775 destroy_msg_out_list(local_msgout_list);
797 if(localnet_msgout_list != NULL){ 776 }
798 GList *route_list = NULL; 777
799 GList *route_node; 778 if (localnet_msgout_list != NULL) {
800 779 GList *route_list = NULL;
801 if(conf.local_net_routes) 780 GList *route_node;
802 route_list = read_route_list(conf.local_net_routes, TRUE); 781
803 else 782 if (conf.local_net_routes)
804 route_list = g_list_append(NULL, create_local_route()); 783 route_list = read_route_list(conf.local_net_routes, TRUE);
805 784 else
806 foreach(route_list, route_node){ 785 route_list = g_list_append(NULL, create_local_route());
807 connect_route *route = (connect_route *)(route_node->data); 786
808 if(!deliver_route_msg_list(route, localnet_msgout_list)) ok = FALSE; 787 foreach(route_list, route_node) {
809 } 788 connect_route *route = (connect_route *) (route_node->data);
810 destroy_msg_out_list(localnet_msgout_list); 789 if (!deliver_route_msg_list(route, localnet_msgout_list))
811 destroy_route_list(route_list); 790 ok = FALSE;
812 } 791 }
813 792 destroy_msg_out_list(localnet_msgout_list);
814 if(other_msgout_list != NULL){ 793 destroy_route_list(route_list);
815 if(!deliver_msgout_list_online(other_msgout_list)) ok = FALSE; 794 }
816 destroy_msg_out_list(other_msgout_list); 795
817 } 796 if (other_msgout_list != NULL) {
818 797 if (!deliver_msgout_list_online(other_msgout_list))
819 foreach(msgout_list, msgout_node){ 798 ok = FALSE;
820 msg_out *msgout = (msg_out *)(msgout_node->data); 799 destroy_msg_out_list(other_msgout_list);
821 spool_unlock(msgout->msg->uid); 800 }
822 } 801
823 802 foreach(msgout_list, msgout_node) {
824 destroy_msg_out_list(msgout_list); 803 msg_out *msgout = (msg_out *) (msgout_node->data);
825 804 spool_unlock(msgout->msg->uid);
826 return ok; 805 }
806
807 destroy_msg_out_list(msgout_list);
808
809 return ok;
827 } 810 }
828 811
829 /* This function searches in the list of rcpt addresses 812 /* This function searches in the list of rcpt addresses
830 for local and 'local net' addresses. Remote addresses 813 for local and 'local net' addresses. Remote addresses
831 which are reachable only when online are treated specially 814 which are reachable only when online are treated specially
832 in another function. 815 in another function.
833 816
834 deliver() is called when a message has just been received and should 817 deliver() is called when a message has just been received and should
835 be delivered immediately. 818 be delivered immediately.
836 */ 819 */
837 gboolean deliver(message *msg) 820 gboolean
838 { 821 deliver(message * msg)
839 gboolean ok; 822 {
840 823 gboolean ok;
841 GList *msg_list = g_list_append(NULL, msg); 824 GList *msg_list = g_list_append(NULL, msg);
842 825
843 ok = deliver_msg_list(msg_list, DLVR_ALL); 826 ok = deliver_msg_list(msg_list, DLVR_ALL);
844 827 g_list_free(msg_list);
845 g_list_free(msg_list); 828
846 829 return ok;
847 return ok; 830 }
848 }
849