/* $NetBSD: mail_addr_map.c,v 1.2 2017/02/14 01:16:45 christos Exp $ */
/*++
/* NAME
/* mail_addr_map 3
/* SUMMARY
/* generic address mapping
/* SYNOPSIS
/* #include <mail_addr_map.h>
/*
/* ARGV *mail_addr_map(path, address, propagate)
/* MAPS *path;
/* const char *address;
/* int propagate;
/* DESCRIPTION
/* mail_addr_map() returns the translation for the named address,
/* or a null pointer if none is found. The result is in canonical
/* external (quoted) form. The search is case insensitive.
/*
/* When the \fBpropagate\fR argument is non-zero,
/* address extensions that aren't explicitly matched in the lookup
/* table are propagated to the result addresses. The caller is
/* expected to pass the result to argv_free().
/*
/* Lookups are performed by mail_addr_find(). When the result has the
/* form \fI@otherdomain\fR, the result is the original user in
/* \fIotherdomain\fR.
/*
/* Arguments:
/* .IP path
/* Dictionary search path (see maps(3)).
/* .IP address
/* The address to be looked up.
/* DIAGNOSTICS
/* Warnings: map lookup returns a non-address result.
/*
/* The path->error value is non-zero when the lookup
/* should be tried again.
/* SEE ALSO
/* mail_addr_find(3), mail address matching
/* mail_addr_crunch(3), mail address parsing and rewriting
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <string.h>
/* Utility library. */
#include <msg.h>
#include <vstring.h>
#include <dict.h>
#include <argv.h>
#include <mymalloc.h>
/* Global library. */
#include <mail_addr_find.h>
#include <mail_addr_crunch.h>
#include <mail_addr_map.h>
/* Application-specific. */
#define STR vstring_str
#define LEN VSTRING_LEN
/* mail_addr_map - map a canonical address */
ARGV *mail_addr_map(MAPS *path, const char *address, int propagate)
{
VSTRING *buffer = 0;
const char *myname = "mail_addr_map";
const char *string;
char *ratsign;
char *extension = 0;
ARGV *argv = 0;
int i;
/*
* Look up the full address; if no match is found, look up the address
* with the extension stripped off, and remember the unmatched extension.
*/
if ((string = mail_addr_find(path, address, &extension)) != 0) {
/*
* Prepend the original user to @otherdomain, but do not propagate
* the unmatched address extension.
*/
if (*string == '@') {
buffer = vstring_alloc(100);
if ((ratsign = strrchr(address, '@')) != 0)
vstring_strncpy(buffer, address, ratsign - address);
else
vstring_strcpy(buffer, address);
if (extension)
vstring_truncate(buffer, LEN(buffer) - strlen(extension));
vstring_strcat(buffer, string);
string = STR(buffer);
}
/*
* Canonicalize and externalize the result, and propagate the
* unmatched extension to each address found.
*/
argv = mail_addr_crunch(string, propagate ? extension : 0);
if (buffer)
vstring_free(buffer);
if (msg_verbose)
for (i = 0; i < argv->argc; i++)
msg_info("%s: %s -> %d: %s", myname, address, i, argv->argv[i]);
if (argv->argc == 0) {
msg_warn("%s lookup of %s returns non-address result \"%s\"",
path->title, address, string);
argv = argv_free(argv);
path->error = DICT_ERR_RETRY;
}
}
/*
* No match found.
*/
else {
if (msg_verbose)
msg_info("%s: %s -> %s", myname, address,
path->error ? "(try again)" : "(not found)");
}
/*
* Cleanup.
*/
if (extension)
myfree(extension);
return (argv);
}
#ifdef TEST
/*
* Proof-of-concept test program. Read an address from stdin, and spit out
* the lookup result.
*/
#include <unistd.h>
#include <mail_conf.h>
#include <vstream.h>
#include <vstring_vstream.h>
#include <mail_params.h>
int main(int argc, char **argv)
{
VSTRING *buffer = vstring_alloc(100);
MAPS *path;
ARGV *result;
/*
* Parse JCL.
*/
if (argc != 2)
msg_fatal("usage: %s database", argv[0]);
/*
* Initialize.
*/
#define UPDATE(dst, src) { myfree(dst); dst = mystrdup(src); }
mail_conf_read();
msg_verbose = 1;
if (chdir(var_queue_dir) < 0)
msg_fatal("chdir %s: %m", var_queue_dir);
path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX \
| DICT_FLAGS_UTF8_REQUEST);
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
msg_info("=== Address extension on, extension propagation on ===");
UPDATE(var_rcpt_delim, "+");
if ((result = mail_addr_map(path, STR(buffer), 1)) != 0)
argv_free(result);
msg_info("=== Address extension on, extension propagation off ===");
if ((result = mail_addr_map(path, STR(buffer), 0)) != 0)
argv_free(result);
msg_info("=== Address extension off ===");
UPDATE(var_rcpt_delim, "");
if ((result = mail_addr_map(path, STR(buffer), 1)) != 0)
argv_free(result);
}
vstring_free(buffer);
maps_free(path);
return (0);
}
#endif