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);
29 int mrcl_validate_pobox_smtp(char *user, char *address, char **ret)
31 char *addr, *retaddr, *p, *lasts = NULL;
32 char *machine = NULL, *m;
33 int oldlen, len, status = MRCL_SUCCESS;
35 /* Make a private copy of address that we can mangle. */
36 addr = strdup(address);
41 /* For each comma-delimited address, canonicalize the hostname and
42 * verify that the address won't cause mail problems.
44 for (p = strtok_r(addr, ", ", &lasts); p; p = strtok_r(NULL, ",", &lasts))
49 *m++ = '\0'; /* get rid of the @ sign */
50 m = strtrim(m); /* get rid of whitespace */
54 com_err(whoami, 0, "No at sign (@) in address \"%s\".", p);
61 machine = canonicalize_hostname(strdup(m));
65 com_err(whoami, 0, "No hostname in address \"%s@\".", p);
70 switch (potype(machine))
73 com_err(whoami, 0, "Cannot forward mail to IMAP server %s",
75 com_err(NULL, 0, "Use \"chpobox -p\" if you are trying to unset "
76 "your mail forwarding.");
83 com_err(whoami, 0, "The name on the POP box (%s) must match "
84 "the username (%s).", p, user);
91 if ((m = strchr(machine, '.')))
93 machine = realloc(machine, strlen(machine) + 6);
94 strcat(machine, ".LOCAL");
100 com_err(whoami, 0, "The address \"%s@%s\" would create a mail "
101 "loop.", p, machine);
102 com_err(NULL, 0, "Set a POP pobox if you want local mail "
104 status = MRCL_REJECT;
109 com_err(whoami, 0, "Cannot forward mail to a local mailing "
110 "address (%s@%s).", p, machine);
111 status = MRCL_REJECT;
116 if (*m != '"' && strcasecmp(m, machine))
118 com_err(whoami, 0, "Warning: hostname %s canonicalized to %s\n",
124 status = MRCL_MOIRA_ERROR;
129 len += (oldlen > 1 ? 2 : 0) + strlen(p) + strlen(machine) + 1;
130 retaddr = realloc(retaddr, len);
131 sprintf(retaddr + oldlen - 1, "%s%s@%s", oldlen > 1 ? ", " : "",
134 machine = NULL; /* Make sure it doesn't get freed again later. */
139 if (status == MRCL_SUCCESS)
148 /* Given a canonicalized machine name, ask the Moira server if it is
149 * of type IMAP, POP, LOCAL, or MAILHUB -- if none of those, we assume
152 static int potype(char *machine)
155 int status, match = 0;
156 static struct save_queue *pop = NULL, *local = NULL;
157 static struct save_queue *mailhub = NULL, *mailhub_name = NULL;
158 static struct save_queue *imap = NULL;
160 /* 0. Check if the machine is an IMAP server. */
163 char *service = "POSTOFFICE";
165 status = mr_query("get_server_locations", 1, &service,
166 save_sloc_machine, imap);
167 if (status && (status != MR_NO_MATCH))
169 com_err(whoami, status, "while reading list of IMAP servers");
174 /* Because of how sq_get_data works, we need to go through the entire
175 * queue even if we find a match, so that it gets reset for the next
178 while (sq_get_data(imap, &name))
180 if (!match && !strcasecmp(name, machine))
188 /* 1. Check if the machine is a POP server. */
191 char *service = "POP";
193 status = mr_query("get_server_locations", 1, &service,
194 save_sloc_machine, pop);
195 if (status && (status != MR_NO_MATCH))
197 com_err(whoami, status, "while reading list of POP servers");
202 while (sq_get_data(pop, &name))
204 if (!match && !strcasecmp(name, machine))
211 /* 2. Check if the machine is "LOCAL". */
214 char *service = "LOCAL";
216 status = mr_query("get_server_locations", 1, &service,
217 save_sloc_machine, local);
218 if (status && (status != MR_NO_MATCH))
220 com_err(whoami, status, "while reading list of LOCAL servers");
225 while (sq_get_data(local, &name))
227 if (!match && !strcasecmp(name, machine))
234 /* 3. Check if the machine is one of the mailhubs. */
237 char *service = "MAILHUB";
238 mailhub = sq_create();
239 status = mr_query("get_server_locations", 1, &service,
240 save_sloc_machine, mailhub);
241 if (status && (status != MR_NO_MATCH))
243 com_err(whoami, status, "while reading list of MAILHUB servers");
248 while (sq_get_data(mailhub, &name))
250 if (!match && !strcasecmp(name, machine))
254 return POTYPE_MAILHUB;
257 /* 4. Check if the machine is one of the external names of the mailhubs. */
261 mailhub_name = sq_create();
265 status = mr_query("get_alias", 3, argv, save_alias_value, mailhub_name);
266 if (status && (status != MR_NO_MATCH))
268 com_err(whoami, status, "while reading list of mailhub names");
273 while (sq_get_data(mailhub_name, &name))
275 if (!match && !strcasecmp(name, machine))
279 return POTYPE_MAILHUB;
284 static int save_sloc_machine(int argc, char **argv, void *sq)
286 sq_save_data(sq, strdup(argv[1]));
290 static int save_alias_value(int argc, char **argv, void *sq)
292 sq_save_data(sq, strdup(argv[2]));