Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #88 from tfitch/JENKINS-21730-bcc-support-in-email…
…-ext

JENKINS-21730 - Add bcc support to email-ext plugin
  • Loading branch information
slide committed Feb 24, 2014
2 parents 624bb6e + 4aacabf commit d97977c
Show file tree
Hide file tree
Showing 14 changed files with 93 additions and 33 deletions.
23 changes: 18 additions & 5 deletions src/main/java/hudson/plugins/emailext/EmailRecipientUtils.java
Expand Up @@ -31,6 +31,7 @@ public class EmailRecipientUtils {

public static final int TO = 0;
public static final int CC = 1;
public static final int BCC = 2;

public static Set<InternetAddress> convertRecipientString(String recipientList, EnvVars envVars)
throws AddressException, UnsupportedEncodingException {
Expand All @@ -42,28 +43,35 @@ public static Set<InternetAddress> convertRecipientString(String recipientList,
final Set<InternetAddress> internetAddresses = new LinkedHashSet<InternetAddress>();
if (!StringUtils.isBlank(recipientList)) {
final String expandedRecipientList = fixupSpaces(envVars.expand(recipientList));
InternetAddress[] all = InternetAddress.parse(expandedRecipientList.replace("cc:", ""));
InternetAddress[] all = InternetAddress.parse(expandedRecipientList.replace("bcc:", "").replace("cc:", ""));
final Set<InternetAddress> to = new LinkedHashSet<InternetAddress>();
final Set<InternetAddress> cc = new LinkedHashSet<InternetAddress>();
final Set<InternetAddress> bcc = new LinkedHashSet<InternetAddress>();
final String defaultSuffix = Mailer.descriptor().getDefaultSuffix();

for(InternetAddress address : all) {
if(address.getPersonal() != null) {
if(expandedRecipientList.contains("cc:" + address.getPersonal()) || expandedRecipientList.contains("cc:\"" + address.toString() + "\"")) {
if(expandedRecipientList.contains("bcc:" + address.getPersonal()) || expandedRecipientList.contains("bcc:\"" + address.toString() + "\"")) {
bcc.add(address);
} else if(expandedRecipientList.contains("cc:" + address.getPersonal()) || expandedRecipientList.contains("cc:\"" + address.toString() + "\"")) {
cc.add(address);
} else {
to.add(address);
}
} else {
if(expandedRecipientList.contains("cc:" + address.toString())) {
if(expandedRecipientList.contains("bcc:" + address.toString())) {
bcc.add(address);
} else if(expandedRecipientList.contains("cc:" + address.toString())) {
cc.add(address);
} else {
to.add(address);
}
}
}

if(type == CC) {
if(type == BCC) {
internetAddresses.addAll(bcc);
} else if(type == CC) {
internetAddresses.addAll(cc);
} else {
internetAddresses.addAll(to);
Expand Down Expand Up @@ -111,6 +119,7 @@ public FormValidation validateFormRecipientList(String recipientList) {
// Try and convert the recipient string to a list of InternetAddress. If this fails then the validation fails.
try {
convertRecipientString(recipientList, new EnvVars(), TO);
convertRecipientString(recipientList, new EnvVars(), BCC);
convertRecipientString(recipientList, new EnvVars(), CC);
return FormValidation.ok();
} catch (AddressException e) {
Expand Down Expand Up @@ -151,11 +160,15 @@ public static boolean isExcludedRecipient(User user, TaskListener listener) {
return false;
}

public static void addAddressesFromRecipientList(Set<InternetAddress> to, Set<InternetAddress> cc, String recipientList,
public static void addAddressesFromRecipientList(Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc, String recipientList,
EnvVars envVars, TaskListener listener) {
try {
Set<InternetAddress> internetAddresses = convertRecipientString(recipientList, envVars, EmailRecipientUtils.TO);
to.addAll(internetAddresses);
if(bcc != null) {
Set<InternetAddress> bccInternetAddresses = convertRecipientString(recipientList, envVars, EmailRecipientUtils.BCC);
bcc.addAll(bccInternetAddresses);
}
if(cc != null) {
Set<InternetAddress> ccInternetAddresses = convertRecipientString(recipientList, envVars, EmailRecipientUtils.CC);
cc.addAll(ccInternetAddresses);
Expand Down
15 changes: 10 additions & 5 deletions src/main/java/hudson/plugins/emailext/ExtendedEmailPublisher.java
Expand Up @@ -503,20 +503,21 @@ private MimeMessage createMail(ExtendedEmailPublisherContext context) throws Mes
// Get the recipients from the global list of addresses
Set<InternetAddress> to = new LinkedHashSet<InternetAddress>();
Set<InternetAddress> cc = new LinkedHashSet<InternetAddress>();
Set<InternetAddress> bcc = new LinkedHashSet<InternetAddress>();

String emergencyReroute = descriptor.getEmergencyReroute();

if (StringUtils.isNotBlank(emergencyReroute)) {
debug(context.getListener().getLogger(), "Emergency reroute turned on");
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, emergencyReroute, env, context.getListener());
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, bcc, emergencyReroute, env, context.getListener());
debug(context.getListener().getLogger(), "Emergency reroute is set to: " + emergencyReroute);
} else {
for (RecipientProvider provider : context.getTrigger().getEmail().getRecipientProviders()) {
provider.addRecipients(context, env, to, cc);
provider.addRecipients(context, env, to, cc, bcc);
}

descriptor.debug(context.getListener().getLogger(), "Adding recipients from trigger recipient list");
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, EmailRecipientUtils.getRecipientList(context, context.getTrigger().getEmail().getRecipientList()), env, context.getListener());
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, bcc, EmailRecipientUtils.getRecipientList(context, context.getTrigger().getEmail().getRecipientList()), env, context.getListener());
}

// remove the excluded recipients
Expand All @@ -528,20 +529,24 @@ private MimeMessage createMail(ExtendedEmailPublisherContext context) throws Mes
}
to.removeAll(excludedRecipients);
cc.removeAll(excludedRecipients);
bcc.removeAll(excludedRecipients);

msg.setRecipients(Message.RecipientType.TO, to.toArray(new InternetAddress[to.size()]));
if (cc.size() > 0) {
msg.setRecipients(Message.RecipientType.CC, cc.toArray(new InternetAddress[cc.size()]));
}
if (bcc.size() > 0) {
msg.setRecipients(Message.RecipientType.BCC, bcc.toArray(new InternetAddress[bcc.size()]));
}

Set<InternetAddress> replyToAddresses = new LinkedHashSet<InternetAddress>();

if (StringUtils.isNotBlank(replyTo)) {
EmailRecipientUtils.addAddressesFromRecipientList(replyToAddresses, null, EmailRecipientUtils.getRecipientList(context, replyTo), env, context.getListener());
EmailRecipientUtils.addAddressesFromRecipientList(replyToAddresses, null, null, EmailRecipientUtils.getRecipientList(context, replyTo), env, context.getListener());
}

if (StringUtils.isNotBlank(context.getTrigger().getEmail().getReplyTo())) {
EmailRecipientUtils.addAddressesFromRecipientList(replyToAddresses, null, EmailRecipientUtils.getRecipientList(context, context.getTrigger().getEmail().getReplyTo()), env, context.getListener());
EmailRecipientUtils.addAddressesFromRecipientList(replyToAddresses, null, null, EmailRecipientUtils.getRecipientList(context, context.getTrigger().getEmail().getReplyTo()), env, context.getListener());
}

if (replyToAddresses.size() > 0) {
Expand Down
Expand Up @@ -24,5 +24,5 @@ public RecipientProviderDescriptor getDescriptor() {
return (RecipientProviderDescriptor) Jenkins.getInstance().getDescriptor(getClass());
}

public abstract void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc);
public abstract void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc);
}
Expand Up @@ -32,7 +32,7 @@ public CulpritsRecipientProvider() {
}

@Override
public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc) {
public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc) {
ExtendedEmailPublisherDescriptor descriptor = Jenkins.getInstance().getDescriptorByType(ExtendedEmailPublisherDescriptor.class);
Set<User> users = context.getBuild().getCulprits();

Expand All @@ -41,7 +41,7 @@ public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Se
String userAddress = EmailRecipientUtils.getUserConfiguredEmail(user);
if (userAddress != null) {
descriptor.debug(context.getListener().getLogger(), "Adding user address %s, they were not considered an excluded committer", userAddress);
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, userAddress, env, context.getListener());
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, bcc, userAddress, env, context.getListener());
} else {
context.getListener().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");
}
Expand Down
Expand Up @@ -26,7 +26,7 @@ public DevelopersRecipientProvider() {
}

@Override
public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc) {
public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc) {
ExtendedEmailPublisherDescriptor descriptor = Jenkins.getInstance().getDescriptorByType(ExtendedEmailPublisherDescriptor.class);
Set<User> users = new HashSet<User>();
for (ChangeLogSet.Entry change : context.getBuild().getChangeSet()) {
Expand All @@ -38,7 +38,7 @@ public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Se
String userAddress = EmailRecipientUtils.getUserConfiguredEmail(user);
if (userAddress != null) {
descriptor.debug(context.getListener().getLogger(), "Adding user address %s, they were not considered an excluded committer", userAddress);
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, userAddress, env, context.getListener());
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, bcc, userAddress, env, context.getListener());
} else {
context.getListener().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");
}
Expand Down
Expand Up @@ -33,11 +33,11 @@ public ListRecipientProvider() {
}

@Override
public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc) {
public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc) {
try {
ExtendedEmailPublisherDescriptor descriptor = Jenkins.getInstance().getDescriptorByType(ExtendedEmailPublisherDescriptor.class);
descriptor.debug(context.getListener().getLogger(), "Adding recipients from project recipient list");
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, EmailRecipientUtils.getRecipientList(context, context.getPublisher().recipientList), env, context.getListener());
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, bcc, EmailRecipientUtils.getRecipientList(context, context.getPublisher().recipientList), env, context.getListener());
} catch (MessagingException ex) {
Logger.getLogger(ListRecipientProvider.class.getName()).log(Level.SEVERE, null, ex);
}
Expand Down
Expand Up @@ -32,7 +32,7 @@ public RequesterRecipientProvider() {
}

@Override
public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc) {
public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc) {
// looking for Upstream build.
AbstractBuild<?, ?> cur = context.getBuild();
Cause.UpstreamCause upc = context.getBuild().getCause(Cause.UpstreamCause.class);
Expand All @@ -45,10 +45,10 @@ public void addRecipients(ExtendedEmailPublisherContext context, EnvVars env, Se
cur = p.getBuildByNumber(upc.getUpstreamBuild());
upc = cur.getCause(Cause.UpstreamCause.class);
}
addUserTriggeringTheBuild(cur, to, cc, env, context.getListener());
addUserTriggeringTheBuild(cur, to, cc, bcc, env, context.getListener());
}

private void addUserTriggeringTheBuild(AbstractBuild<?, ?> build, Set<InternetAddress> to, Set<InternetAddress> cc,
private void addUserTriggeringTheBuild(AbstractBuild<?, ?> build, Set<InternetAddress> to, Set<InternetAddress> cc, Set<InternetAddress> bcc,
EnvVars env, TaskListener listener) {
User user = getByUserIdCause(build);
if (user == null) {
Expand All @@ -58,10 +58,10 @@ private void addUserTriggeringTheBuild(AbstractBuild<?, ?> build, Set<InternetAd
if (user != null) {
String adrs = user.getProperty(Mailer.UserProperty.class).getAddress();
if (adrs != null) {
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, adrs, env, listener);
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, bcc, adrs, env, listener);
} else {
listener.getLogger().println("The user does not have a configured email address, trying the user's id");
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, user.getId(), env, listener);
EmailRecipientUtils.addAddressesFromRecipientList(to, cc, bcc, user.getId(), env, listener);
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/main/webapp/help/globalConfig/defaultRecipients.html
Expand Up @@ -4,6 +4,7 @@
project configuration. You may use the $DEFAULT_RECIPIENTS
token in projects to include this default list, as well as
add new addresses at the project level.
To CC someone instead of putting them in the To list, add
cc: before the email address (e.g., cc:someone@somewhere.com).
To CC or BCC someone instead of putting them in the To list, add
cc: or bcc: before the email address
(e.g., cc:someone@example.com, bcc:bob@example.com).
</div>
Expand Up @@ -2,6 +2,6 @@
自訂電子郵件通知的預設收件人清單。
如果沒有被專案設定覆蓋掉,就會使用這一組清單。
您可以在專案中使用 <code>$DEFAULT_RECIPIENTS</code> Token,在專案層級設定其他收件人的同時也加入這份預設清單。
要是想把某些人放在副本清單,而不是放在收件人清單裡,請在信箱前面加上 <code>cc:</code>
(例如: <code>cc:someone@somewhere.com</code>)。
要是想把某些人放在副本清單,而不是放在收件人清單裡,請在信箱前面加上 <code>cc:/bcc:</code>
(例如: <code>cc:someone@example.com, bcc:bob@example.com</code>)。
</div>
5 changes: 3 additions & 2 deletions src/main/webapp/help/projectConfig/globalRecipientList.html
@@ -1,6 +1,7 @@
<div>
This is a comma separated list (optional whitespace after commas) of email addresses
that should receive emails. May contain references to build parameters.
To CC someone instead of putting them in the To list, add cc: before the email address
(e.g., cc:someone@somewhere.com).
To CC or BCC someone instead of putting them in the To list, add
cc: or bcc: before the email address
(e.g., cc:someone@example.com, bcc:bob@example.com).
</div>
Expand Up @@ -2,5 +2,5 @@
要接收本觸發程序送出郵件的收件者信箱清單,多筆信箱之間以半形逗號隔開 (逗號後可以接空格)。
可以參照到建置參數。
要是想把某些人放在副本清單,而不是放在收件人清單裡,請在信箱前面加上 <code>cc:</code>
(例如: <code>cc:someone@somewhere.com</code>)。
(例如: <code>cc:someone@example.com, bcc:bob@example.com</code>)。
</div>
@@ -1,6 +1,7 @@
<div>
This is a comma separated list (optional whitespace after commas) of email addresses
that should receive emails for this trigger. May contain references to build parameters.
To CC someone instead of putting them in the To list, add cc: before the email address
(e.g., cc:someone@somewhere.com).
To CC or BCC someone instead of putting them in the To list, add
cc: or bcc: before the email address
(e.g., cc:someone@example.com, bcc:bob@example.com).
</div>
@@ -1,6 +1,6 @@
<div>
要接收本觸發程序送出郵件的收件者信箱清單,多筆信箱之間以半形逗號隔開 (逗號後可以接空格)。
可以參照到建置參數。
要是想把某些人放在副本清單,而不是放在收件人清單裡,請在信箱前面加上 <code>cc:</code>
(例如: <code>cc:someone@somewhere.com</code>)。
要是想把某些人放在副本清單,而不是放在收件人清單裡,請在信箱前面加上 <code>cc:/bcc:</code>
(例如: <code>cc:someone@example.com, bcc:bob@example.com</code>)。
</div>
Expand Up @@ -173,6 +173,45 @@ public void testCC()
assertTrue(internetAddresses.contains(new InternetAddress("slide.o.mix@gmail.com")));
}

@Test
public void testBCC()
throws Exception {
envVars.put("EMAIL_LIST", "ashlux@gmail.com, bcc:slide.o.mix@gmail.com, another@gmail.com");

Set<InternetAddress> internetAddresses = emailRecipientUtils.convertRecipientString("$EMAIL_LIST", envVars);

assertEquals(2, internetAddresses.size());
assertTrue(internetAddresses.contains(new InternetAddress("ashlux@gmail.com")));
assertTrue(internetAddresses.contains(new InternetAddress("another@gmail.com")));

internetAddresses = emailRecipientUtils.convertRecipientString("$EMAIL_LIST", envVars, EmailRecipientUtils.BCC);

assertEquals(1, internetAddresses.size());
assertTrue(internetAddresses.contains(new InternetAddress("slide.o.mix@gmail.com")));
}

@Test
public void testBCCandCC()
throws Exception {
envVars.put("EMAIL_LIST", "ashlux@gmail.com, bcc:slide.o.mix@gmail.com, another@gmail.com, cc:example@gmail.com");

Set<InternetAddress> internetAddresses = emailRecipientUtils.convertRecipientString("$EMAIL_LIST", envVars);

assertEquals(2, internetAddresses.size());
assertTrue(internetAddresses.contains(new InternetAddress("ashlux@gmail.com")));
assertTrue(internetAddresses.contains(new InternetAddress("another@gmail.com")));

internetAddresses = emailRecipientUtils.convertRecipientString("$EMAIL_LIST", envVars, EmailRecipientUtils.BCC);

assertEquals(1, internetAddresses.size());
assertTrue(internetAddresses.contains(new InternetAddress("slide.o.mix@gmail.com")));

internetAddresses = emailRecipientUtils.convertRecipientString("$EMAIL_LIST", envVars, EmailRecipientUtils.CC);

assertEquals(1, internetAddresses.size());
assertTrue(internetAddresses.contains(new InternetAddress("example@gmail.com")));
}

@Test
public void testUTF8()
throws Exception {
Expand Down

0 comments on commit d97977c

Please sign in to comment.