/******************************************************************************* * * Copyright (c) 2004-2009 Oracle Corporation. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Kohsuke Kawaguchi, Luca Domenico Milanesio * * *******************************************************************************/ package hudson.tasks; import hudson.Extension; import hudson.ExtensionList; import hudson.ExtensionListView; import hudson.ExtensionPoint; import hudson.model.Hudson; import hudson.model.User; import hudson.model.UserProperty; import hudson.scm.SCM; import java.util.List; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Infers e-mail addresses for the user when none is specified. * * <p> This is an extension point of Hudson. Plugins tha contribute new * implementation of this class should put {@link Extension} on your * implementation class, like this: * * <pre> * @Extension * class MyMailAddressResolver extends {@link MailAddressResolver} { * ... * } * </pre> * * <h2>Techniques</h2> <p> User identity in Hudson is global, and not specific * to a particular job. As a result, mail address resolution only receives * {@link User}, which by itself doesn't really have that much information in * it. * * <p> So the common technique for a mail address resolution is to define your * own {@link UserProperty} types and add it to {@link User} objects where more * context is available. For example, an {@link SCM} implementation can have a * lot more information about a particular user during a check out, so that * would be a good place to capture information as {@link UserProperty}, which * then later used by a {@link MailAddressResolver}. * * @author Kohsuke Kawaguchi * @since 1.192 */ public abstract class MailAddressResolver implements ExtensionPoint { /** * Infers e-mail address of the given user. * * <p> This method is called when a {@link User} without explicitly * configured e-mail address is used, as an attempt to infer e-mail address. * * <p> The normal strategy is to look at {@link User#getProjects() the projects that the user * is participating}, then use the repository information to infer the * e-mail address. * * <p> When multiple resolvers are installed, they are consulted in order * and the search will be over when an address is inferred by someone. * * <p> Since {@link MailAddressResolver} is singleton, this method can be * invoked concurrently from multiple threads. * * @return null if the inference failed. */ public abstract String findMailAddressFor(User u); public static String resolve(User u) { LOGGER.fine("Resolving e-mail address for \"" + u + "\" ID=" + u.getId()); for (MailAddressResolver r : all()) { String email = r.findMailAddressFor(u); if (email != null) { LOGGER.fine(r + " resolved " + u.getId() + " to " + email); return email; } } // fall back logic String extractedAddress = extractAddressFromId(u.getFullName()); if (extractedAddress != null) { return extractedAddress; } if (u.getFullName().contains("@")) // this already looks like an e-mail ID { return u.getFullName(); } String ds = Mailer.descriptor().getDefaultSuffix(); if (ds != null) { // another common pattern is "DOMAIN\person" in Windows. Only // do this when this full name is not manually set. see HUDSON-5164 Matcher m = WINDOWS_DOMAIN_REGEXP.matcher(u.getFullName()); if (m.matches() && u.getFullName().replace('\\', '_').equals(u.getId())) { return m.group(1) + ds; // user+defaultSuffix } return u.getId() + ds; } else { return null; } } /** * Tries to extract an email address from the user id, or returns null */ private static String extractAddressFromId(String id) { Matcher m = EMAIL_ADDRESS_REGEXP.matcher(id); if (m.matches()) { return m.group(1); } return null; } /** * Matches strings like "Kohsuke Kawaguchi <kohsuke.kawaguchi@sun.com>" * @see #extractAddressFromId(String) */ private static final Pattern EMAIL_ADDRESS_REGEXP = Pattern.compile("^.*<([^>]+)>.*$"); /** * Matches something like "DOMAIN\person" */ private static final Pattern WINDOWS_DOMAIN_REGEXP = Pattern.compile("[^\\\\ ]+\\\\([^\\\\ ]+)"); /** * All registered {@link MailAddressResolver} implementations. * * @deprecated as of 1.286 Use {@link #all()} for read access and * {@link Extension} for registration. */ public static final List<MailAddressResolver> LIST = ExtensionListView.createList(MailAddressResolver.class); /** * Returns all the registered {@link MailAddressResolver} descriptors. */ public static ExtensionList<MailAddressResolver> all() { return Hudson.getInstance().getExtensionList(MailAddressResolver.class); } private static final Logger LOGGER = Logger.getLogger(MailAddressResolver.class.getName()); }