3 * Shared routines for pobox changing.
5 * Copyright (C) 1999 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
10 #include <mit-copyright.h>
22 enum { POTYPE_ERROR, POTYPE_POP, POTYPE_LOCAL, POTYPE_MAILHUB, POTYPE_SMTP, POTYPE_IMAP };
23 static int potype(char *machine);
24 static int save_sloc_machine(int argc, char **argv, void *sq);
25 static int save_alias_value(int argc, char **argv, void *sq);
30 #define strtok_r(s, tokens, resume) strtok(s, tokens)
33 int mrcl_validate_pobox_smtp(char *user, char *address, char **ret)
35 char *addr, *retaddr, *p, *lasts = NULL;
36 char *machine = NULL, *m;
37 int oldlen, len, status = MRCL_SUCCESS;
39 /* Make a private copy of address that we can mangle. */
40 addr = strdup(address);
45 /* For each comma-delimited address, canonicalize the hostname and
46 * verify that the address won't cause mail problems.
48 for (p = strtok_r(addr, ", ", &lasts); p; p = strtok_r(NULL, ",", &lasts))
53 *m++ = '\0'; /* get rid of the @ sign */
54 m = strtrim(m); /* get rid of whitespace */
58 com_err(whoami, 0, "No at sign (@) in address \"%s\".", p);
65 machine = canonicalize_hostname(strdup(m));
69 com_err(whoami, 0, "No hostname in address \"%s@\".", p);
74 switch (potype(machine))
77 com_err(whoami, 0, "Cannot forward mail to IMAP server %s",
79 com_err(NULL, 0, "Use \"chpobox -p\" if you are trying to unset "
80 "your mail forwarding.");
87 com_err(whoami, 0, "The name on the POP box (%s) must match "
88 "the username (%s).", p, user);
95 if ((m = strchr(machine, '.')))
97 machine = realloc(machine, strlen(machine) + 6);
98 strcat(machine, ".LOCAL");
102 if (!strcmp(p, user))
104 com_err(whoami, 0, "The address \"%s@%s\" would create a mail "
105 "loop.", p, machine);
106 com_err(NULL, 0, "Set a POP pobox if you want local mail "
108 status = MRCL_REJECT;
113 com_err(whoami, 0, "Cannot forward mail to a local mailing "
114 "address (%s@%s).", p, machine);
115 status = MRCL_REJECT;
120 if (*m != '"' && strcasecmp(m, machine))
122 com_err(whoami, 0, "Warning: hostname %s canonicalized to %s\n",
128 status = MRCL_MOIRA_ERROR;
133 len += (oldlen > 1 ? 2 : 0) + strlen(p) + strlen(machine) + 1;
134 retaddr = realloc(retaddr, len);
135 sprintf(retaddr + oldlen - 1, "%s%s@%s", oldlen > 1 ? ", " : "",
138 machine = NULL; /* Make sure it doesn't get freed again later. */
143 if (status == MRCL_SUCCESS)
152 /* Given a canonicalized machine name, ask the Moira server if it is
153 * of type IMAP, POP, LOCAL, or MAILHUB -- if none of those, we assume
156 static int potype(char *machine)
159 int status, match = 0;
160 static struct save_queue *pop = NULL, *local = NULL;
161 static struct save_queue *mailhub = NULL, *mailhub_name = NULL;
162 static struct save_queue *imap = NULL;
164 /* 0. Check if the machine is an IMAP server. */
167 char *service = "POSTOFFICE";
169 status = mr_query("get_server_locations", 1, &service,
170 save_sloc_machine, imap);
171 if (status && (status != MR_NO_MATCH))
173 com_err(whoami, status, "while reading list of IMAP servers");
178 /* Because of how sq_get_data works, we need to go through the entire
179 * queue even if we find a match, so that it gets reset for the next
182 while (sq_get_data(imap, &name))
184 if (!match && !strcasecmp(name, machine))
192 /* 1. Check if the machine is a POP server. */
195 char *service = "POP";
197 status = mr_query("get_server_locations", 1, &service,
198 save_sloc_machine, pop);
199 if (status && (status != MR_NO_MATCH))
201 com_err(whoami, status, "while reading list of POP servers");
206 while (sq_get_data(pop, &name))
208 if (!match && !strcasecmp(name, machine))
215 /* 2. Check if the machine is "LOCAL". */
218 char *service = "LOCAL";
220 status = mr_query("get_server_locations", 1, &service,
221 save_sloc_machine, local);
222 if (status && (status != MR_NO_MATCH))
224 com_err(whoami, status, "while reading list of LOCAL servers");
229 while (sq_get_data(local, &name))
231 if (!match && !strcasecmp(name, machine))
238 /* 3. Check if the machine is one of the mailhubs. */
241 char *service = "MAILHUB";
242 mailhub = sq_create();
243 status = mr_query("get_server_locations", 1, &service,
244 save_sloc_machine, mailhub);
245 if (status && (status != MR_NO_MATCH))
247 com_err(whoami, status, "while reading list of MAILHUB servers");
252 while (sq_get_data(mailhub, &name))
254 if (!match && !strcasecmp(name, machine))
258 return POTYPE_MAILHUB;
261 /* 4. Check if the machine is one of the external names of the mailhubs. */
265 mailhub_name = sq_create();
269 status = mr_query("get_alias", 3, argv, save_alias_value, mailhub_name);
270 if (status && (status != MR_NO_MATCH))
272 com_err(whoami, status, "while reading list of mailhub names");
277 while (sq_get_data(mailhub_name, &name))
279 if (!match && !strcasecmp(name, machine))
283 return POTYPE_MAILHUB;
288 static int save_sloc_machine(int argc, char **argv, void *sq)
290 sq_save_data(sq, strdup(argv[1]));
294 static int save_alias_value(int argc, char **argv, void *sq)
296 sq_save_data(sq, strdup(argv[2]));