masqmail

view src/alias.c @ 75:257a9e6d1a8e

fixed correct processing of mails with data lines longer 4096 chars Mail messages with lines longer than 4096 chars were already read correctly, i.e. the spool files were correct. This commit fixes the reading of spool files with long lines. The old behavior was that the message body was truncated right before the first line longer 4096 chars. The number comes from MAX_DATALINE.
author meillo@marmaro.de
date Wed, 16 Jun 2010 19:06:34 +0200
parents 26e34ae9a3e3
children a80ebfa16cd5
line source
1 /* MasqMail
2 Copyright (C) 2000-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 "masqmail.h"
20 #include <fnmatch.h>
22 gboolean
23 addr_is_local(address * addr)
24 {
25 GList *dom_node;
26 GList *addr_node;
27 address *a;
29 foreach(conf.local_hosts, dom_node) {
30 if (addr->domain == NULL)
31 return TRUE;
32 if (fnmatch(dom_node->data, addr->domain, FNM_CASEFOLD) == 0) {
33 foreach(conf.not_local_addresses, addr_node) {
34 a = create_address_qualified(addr_node->data, TRUE, conf.host_name);
35 if (addr_isequal(a, addr)) {
36 destroy_address(a);
37 return FALSE;
38 }
39 destroy_address(a);
40 }
41 return TRUE;
42 }
43 }
44 foreach(conf.local_addresses, addr_node) {
45 a = create_address_qualified(addr_node->data, TRUE, conf.host_name);
46 if (addr_isequal(a, addr)) {
47 destroy_address(a);
48 return TRUE;
49 }
50 destroy_address(a);
51 }
52 return FALSE;
53 }
55 static gboolean
56 addr_isequal_alias(address * addr1, address * addr2)
57 {
58 return (conf.alias_local_cmp(addr1->local_part, addr2->local_part) == 0)
59 && (strcasecmp(addr1->domain, addr2->domain) == 0);
60 }
62 static GList*
63 parse_list(gchar * line)
64 {
65 GList *list = NULL;
66 gchar buf[256];
67 gchar *p, *q;
69 p = line;
70 while (*p != '\0') {
71 q = buf;
72 while (isspace(*p))
73 p++;
74 if (*p != '\"') {
75 while (*p && (*p != ',') && (q < buf + 255))
76 *(q++) = *(p++);
77 *q = '\0';
78 } else {
79 gboolean escape = FALSE;
80 p++;
81 while (*p && (*p != '\"' || escape) && (q < buf + 255)) {
82 if ((*p == '\\') && !escape)
83 escape = TRUE;
84 else {
85 escape = FALSE;
86 *(q++) = *p;
87 }
88 p++;
89 }
90 *q = '\0';
91 while (*p && (*p != ','))
92 p++;
93 }
94 list = g_list_append(list, g_strdup(g_strchomp(buf)));
95 if (*p)
96 p++;
97 }
98 return list;
99 }
101 GList*
102 alias_expand(GList * alias_table, GList * rcpt_list, GList * non_rcpt_list)
103 {
104 GList *done_list = NULL;
105 GList *rcpt_node = g_list_copy(rcpt_list);
107 while (rcpt_node != NULL) {
108 address *addr = (address *) (rcpt_node->data);
109 DEBUG(5) debugf("alias_expand begin: '%s@%s'\n", addr->local_part, addr->domain);
110 /* if(addr_is_local(addr) && (addr->local_part[0] != '|') && */
111 if (addr_is_local(addr) && !(addr->flags & ADDR_FLAG_NOEXPAND)) {
112 gchar *val;
114 /* special handling for postmaster */
115 if (strcasecmp(addr->local_part, "postmaster") == 0)
116 val = (gchar *) table_find_func(alias_table, addr->local_part, strcasecmp);
117 else
118 val = (gchar *) table_find_func(alias_table, addr->local_part, conf.alias_local_cmp);
120 DEBUG(5) debugf("alias: '%s' is local\n", addr->local_part);
121 if (val != NULL) {
122 GList *val_list = parse_list(val);
123 GList *val_node;
124 GList *alias_list = NULL;
126 DEBUG(5) debugf("alias: '%s' -> '%s'\n", addr->local_part, val);
127 foreach(val_list, val_node) {
128 gchar *val = (gchar *) (val_node->data);
129 address *alias_addr;
130 address *addr_parent = NULL;
132 if (val[0] == '|') {
133 DEBUG(5) debugf("alias: %s is a pipe address\n", val);
134 alias_addr = create_address_pipe(val);
135 DEBUG(5) debugf("alias_pipe: %s is a pipe address\n", alias_addr->local_part);
136 } else if (val[0] == '\\') {
137 DEBUG(5) debugf("alias: shall not be expanded: '%s'\n", val);
138 alias_addr = create_address_qualified(&(val[1]), TRUE, conf.host_name);
139 alias_addr->flags |= ADDR_FLAG_NOEXPAND;
140 DEBUG(5) debugf("alias: not expanded: '%s'\n", alias_addr->local_part);
141 } else {
142 alias_addr = create_address_qualified(val, TRUE, conf.host_name);
144 /* search in parents for loops: */
145 for (addr_parent = addr; addr_parent; addr_parent = addr_parent->parent) {
146 if (addr_isequal_alias (alias_addr, addr_parent)) {
147 logwrite(LOG_ALERT,
148 "detected alias loop, (ignoring): %s@%s -> %s@%s\n",
149 addr_parent->local_part,
150 addr_parent->domain,
151 addr->local_part, addr->domain);
152 break;
153 }
154 }
155 }
156 if (!addr_parent) {
157 alias_list = g_list_append(alias_list, alias_addr);
158 alias_addr->parent = addr;
159 }
160 g_free(val);
161 }
162 g_list_free(val_list);
163 addr->children = g_list_copy(alias_list);
164 rcpt_node = g_list_concat(rcpt_node, alias_list);
165 } else {
166 DEBUG(5) debugf("alias: '%s' is completed\n", addr->local_part);
167 done_list = g_list_append(done_list, addr);
168 }
169 } else {
170 DEBUG(5) debugf("alias: '%s@%s' is not local\n", addr->local_part, addr->domain);
171 done_list = g_list_append(done_list, addr);
172 }
173 rcpt_node = g_list_next(rcpt_node);
174 }
176 /* delete addresses from done_list if they are in the non_rcpt_list */
177 if (non_rcpt_list) {
178 GList *rcpt_node_next;
179 for (rcpt_node = g_list_first(done_list); rcpt_node; rcpt_node = rcpt_node_next) {
180 address *addr = (address *) (rcpt_node->data);
181 GList *non_node;
183 rcpt_node_next = g_list_next(rcpt_node);
185 foreach(non_rcpt_list, non_node) {
186 address *non_addr = (address *) (non_node->data);
187 if (addr_isequal(addr, non_addr)) {
188 done_list = g_list_remove_link(done_list, rcpt_node);
189 g_list_free_1(rcpt_node);
190 addr_mark_delivered(addr); /* this address is still in the children lists of the original address */
191 break;
192 }
193 }
194 }
195 }
196 return done_list;
197 }