
hudson.plugins.emailext.ExtendedEmailPublisher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of email-ext Show documentation
Show all versions of email-ext Show documentation
Hudson Email Extension Plugin
The newest version!
package hudson.plugins.emailext;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.model.User;
import hudson.plugins.emailext.plugins.ContentBuilder;
import hudson.plugins.emailext.plugins.EmailTrigger;
import hudson.plugins.emailext.plugins.EmailTriggerDescriptor;
import hudson.scm.ChangeLogSet.Entry;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.MailMessageIdAction;
import hudson.tasks.Mailer;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
/**
* {@link Publisher} that sends notification e-mail.
*/
public class ExtendedEmailPublisher extends Notifier {
private static final Logger LOGGER = Logger.getLogger(Mailer.class.getName());
public static final Map EMAIL_TRIGGER_TYPE_MAP
= new HashMap();
public static final String DEFAULT_SUBJECT_TEXT = "$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!";
public static final String DEFAULT_BODY_TEXT = "$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS:\n\n" +
"Check console output at $BUILD_URL to view the results.";
public static final String PROJECT_DEFAULT_SUBJECT_TEXT = "$PROJECT_DEFAULT_SUBJECT";
public static final String PROJECT_DEFAULT_BODY_TEXT = "$PROJECT_DEFAULT_CONTENT";
public static final String CHARSET = "utf-8";
public static void addEmailTriggerType(EmailTriggerDescriptor triggerType) throws EmailExtException {
if (EMAIL_TRIGGER_TYPE_MAP.containsKey(triggerType.getMailerId())) {
throw new EmailExtException("An email trigger type with name " +
triggerType.getTriggerName() + " was already added.");
}
EMAIL_TRIGGER_TYPE_MAP.put(triggerType.getMailerId(), triggerType);
}
public static void removeEmailTriggerType(EmailTriggerDescriptor triggerType) {
if (EMAIL_TRIGGER_TYPE_MAP.containsKey(triggerType.getMailerId())) {
EMAIL_TRIGGER_TYPE_MAP.remove(triggerType.getMailerId());
}
}
public static EmailTriggerDescriptor getEmailTriggerType(String mailerId) {
return EMAIL_TRIGGER_TYPE_MAP.get(mailerId);
}
public static Collection getEmailTriggers() {
return EMAIL_TRIGGER_TYPE_MAP.values();
}
public static Collection getEmailTriggerNames() {
return EMAIL_TRIGGER_TYPE_MAP.keySet();
}
public static List getTriggersForNonConfiguredInstance() {
List retList = new ArrayList();
for (String mailerId : EMAIL_TRIGGER_TYPE_MAP.keySet()) {
retList.add(EMAIL_TRIGGER_TYPE_MAP.get(mailerId).getNewInstance(null));
}
return retList;
}
/**
* A comma-separated list of email recipient that will be used for every trigger.
*/
public String recipientList;
/**
* This is the list of email triggers that the project has configured
*/
public List configuredTriggers = new ArrayList();
/**
* The contentType of the emails for this project (text/html, text/plain, etc).
*/
public String contentType;
/**
* The default subject of the emails for this project. ($PROJECT_DEFAULT_SUBJECT)
*/
public String defaultSubject;
/**
* The default body of the emails for this project. ($PROJECT_DEFAULT_BODY)
*/
public String defaultContent;
/**
* The project wide set of attachments.
*/
public String attachmentsPattern;
/**
* True to attach the log from the build to the email.
*/
public boolean attachBuildLog;
/**
* True to compress the log from the build before attaching to the email
*/
public boolean compressBuildLog;
/**
* Get the list of configured email triggers for this project.
*/
public List getConfiguredTriggers() {
if (configuredTriggers == null) {
configuredTriggers = new ArrayList();
}
return configuredTriggers;
}
/**
* Get the list of non-configured email triggers for this project.
*/
public List getNonConfiguredTriggers() {
List confTriggers = getConfiguredTriggers();
List retList = new ArrayList();
for (String mailerId : EMAIL_TRIGGER_TYPE_MAP.keySet()) {
boolean contains = false;
for (EmailTrigger trigger : confTriggers) {
if (trigger.getDescriptor().getMailerId().equals(mailerId)) {
contains = true;
break;
}
}
if (!contains) {
retList.add(EMAIL_TRIGGER_TYPE_MAP.get(mailerId).getNewInstance(null));
}
}
return retList;
}
/**
* Return true if the project has been configured, otherwise returns false
*/
public boolean isConfigured() {
return !getConfiguredTriggers().isEmpty();
}
/**
* Return true if the project has been configured, otherwise returns false
*/
public boolean getConfigured() {
return isConfigured();
}
@Override
public boolean prebuild(AbstractBuild, ?> build, BuildListener listener) {
return _perform(build, listener, true);
}
@Override
public boolean perform(AbstractBuild, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
return _perform(build, listener, false);
}
private boolean _perform(AbstractBuild, ?> build, BuildListener listener, boolean forPreBuild) {
boolean emailTriggered = false;
Map triggered = new HashMap();
for (EmailTrigger trigger : configuredTriggers) {
if (trigger.isPreBuild() == forPreBuild && trigger.trigger(build)) {
String tName = trigger.getDescriptor().getTriggerName();
triggered.put(tName, trigger);
listener.getLogger().println("Email was triggered for: " + tName);
emailTriggered = true;
}
}
//Go through and remove triggers that are replaced by others
List replacedTriggers = new ArrayList();
for (String triggerName : triggered.keySet()) {
replacedTriggers.addAll(triggered.get(triggerName).getDescriptor().getTriggerReplaceList());
}
for (String triggerName : replacedTriggers) {
triggered.remove(triggerName);
listener.getLogger()
.println("Trigger " + triggerName + " was overridden by another trigger and will not send an email.");
}
if (emailTriggered && triggered.isEmpty()) {
listener.getLogger()
.println("There is a circular trigger replacement with the email triggers. No email is sent.");
return false;
} else if (triggered.isEmpty()) {
listener.getLogger().println("No emails were triggered.");
return true;
}
for (String triggerName : triggered.keySet()) {
listener.getLogger().println("Sending email for trigger: " + triggerName);
sendMail(triggered.get(triggerName).getEmail(), build, listener);
}
return true;
}
private boolean sendMail(EmailType mailType, AbstractBuild, ?> build, BuildListener listener) {
try {
MimeMessage msg = createMail(mailType, build, listener);
Address[] allRecipients = msg.getAllRecipients();
if (allRecipients != null) {
StringBuilder buf = new StringBuilder("Sending email to:");
for (Address a : allRecipients) {
buf.append(' ').append(a);
}
listener.getLogger().println(buf);
Transport.send(msg);
if (build.getAction(MailMessageIdAction.class) == null) {
build.addAction(new MailMessageIdAction(msg.getMessageID()));
}
return true;
} else {
listener.getLogger().println("An attempt to send an e-mail"
+ " to empty list of recipients, ignored.");
}
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Could not send email.", e);
e.printStackTrace(listener.error("Could not send email as a part of the post-build publishers."));
}
return false;
}
private MimeMessage createMail(EmailType type, AbstractBuild, ?> build, BuildListener listener)
throws MessagingException, IOException, InterruptedException {
boolean overrideGlobalSettings = ExtendedEmailPublisher.DESCRIPTOR.getOverrideGlobalSettings();
MimeMessage msg;
// If not overriding global settings, use the Mailer class to create a session and set the from address
// Else we'll do it ourselves
if (!overrideGlobalSettings) {
msg = new MimeMessage(Mailer.descriptor().createSession());
msg.setFrom(new InternetAddress(Mailer.descriptor().getAdminAddress()));
} else {
msg = new MimeMessage(ExtendedEmailPublisher.DESCRIPTOR.createSession());
msg.setFrom(new InternetAddress(ExtendedEmailPublisher.DESCRIPTOR.getAdminAddress()));
}
// Set the contents of the email
// Set the contents of the email
msg.addHeader("X-Hudson-Job", build.getProject().getDisplayName());
if (build.getResult() != null) {
msg.addHeader("X-Hudson-Result", build.getResult().toString());
}
msg.setSentDate(new Date());
setSubject(type, build, msg);
Multipart multipart = new MimeMultipart();
MimeBodyPart bp1 = new MimeBodyPart();
setContent(type, build, bp1);
multipart.addBodyPart(bp1);
EnvVars env = build.getEnvironment(listener);
// Get the recipients from the global list of addresses
Set recipientAddresses = new LinkedHashSet();
if (type.getSendToRecipientList()) {
addAddressesFromRecipientList(recipientAddresses, recipientList, env, listener);
}
// Get the list of developers who made changes between this build and the last
// if this mail type is configured that way
if (type.getSendToDevelopers()) {
Set users;
if (type.getIncludeCulprits()) {
users = build.getCulprits();
} else {
users = new HashSet();
for (Entry change : build.getChangeSet()) {
users.add(change.getAuthor());
}
}
for (User user : users) {
String adrs = user.getProperty(Mailer.UserProperty.class).getAddress();
if (adrs != null) {
addAddressesFromRecipientList(recipientAddresses, adrs, env, listener);
} else {
listener.getLogger()
.println("Failed to send e-mail to " + user.getFullName()
+ " because no e-mail address is known, and no default e-mail domain is configured");
}
}
}
//Get the list of recipients that are uniquely specified for this type of email
if (type.getRecipientList() != null && type.getRecipientList().trim().length() > 0) {
addAddressesFromRecipientList(recipientAddresses, type.getRecipientList(), env, listener);
}
msg.setRecipients(Message.RecipientType.TO,
recipientAddresses.toArray(new InternetAddress[recipientAddresses.size()]));
AbstractBuild, ?> pb = build.getPreviousBuild();
if (pb != null) {
// Send mails as replies until next successful build
MailMessageIdAction b = pb.getAction(MailMessageIdAction.class);
if (b != null && pb.getResult() != Result.SUCCESS) {
msg.setHeader("In-Reply-To", b.messageId);
msg.setHeader("References", b.messageId);
}
}
final ExtendedEmailPublisherContext context = new ExtendedEmailPublisherContext(this, build, null, listener);
AttachmentUtils attachments = new AttachmentUtils(attachmentsPattern);
attachments.attach(multipart, context);
if (attachBuildLog || type.getAttachBuildLog()) {
listener.getLogger().println("Request made to attach build log");
AttachmentUtils.attachBuildLog(context, multipart, compressBuildLog);
}
msg.setContent(multipart);
return msg;
}
private void setSubject(final EmailType type, final AbstractBuild, ?> build, MimeMessage msg)
throws MessagingException {
String subject = new ContentBuilder().transformText(type.getSubject(), this, type, build);
msg.setSubject(subject, CHARSET);
}
private void setContent(final EmailType type, final AbstractBuild, ?> build, MimeBodyPart bp)
throws MessagingException {
final String text = new ContentBuilder().transformText(type.getBody(), this, type, build);
String messageContentType = contentType;
// contentType is null if the project was not reconfigured after upgrading.
if (messageContentType == null || "default".equals(messageContentType)) {
messageContentType = DESCRIPTOR.getDefaultContentType();
// The defaultContentType is null if the main Hudson configuration
// was not reconfigured after upgrading.
if (messageContentType == null) {
messageContentType = "text/plain";
}
}
messageContentType += "; charset=" + CHARSET;
bp.setContent(text, messageContentType);
}
private static void addAddressesFromRecipientList(Set addresses, String recipientList,
EnvVars envVars, BuildListener listener) {
try {
Set internetAddresses = new EmailRecepientUtils().
convertRecipientString(recipientList, envVars, true);
addresses.addAll(internetAddresses);
} catch (AddressException ae) {
LOGGER.log(Level.WARNING, "Could not create email address.", ae);
listener.getLogger().println("Failed to create e-mail address for " + ae.getRef());
}
}
@Override
public boolean needsToRunAfterFinalized() {
return true;
}
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.BUILD;
}
@Override
public BuildStepDescriptor getDescriptor() {
return DESCRIPTOR;
}
@Extension
public static final ExtendedEmailPublisherDescriptor DESCRIPTOR = new ExtendedEmailPublisherDescriptor();
// The descriptor has been moved but we need to maintain the old descriptor for backwards compatibility reasons.
@SuppressWarnings({"UnusedDeclaration"})
public static final class DescriptorImpl
extends ExtendedEmailPublisherDescriptor {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy