PageRenderTime 48ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/java/com/redradishtech/jira/ccmailer/UnsubscribeCCField.java

https://bitbucket.org/redradish/ccmailer-44x
Java | 176 lines | 141 code | 18 blank | 17 comment | 8 complexity | 0893d38c3788637143591b7f469f3f0b MD5 | raw file
  1. package com.redradishtech.jira.ccmailer;
  2. import com.atlassian.jira.ManagerFactory;
  3. import com.atlassian.jira.issue.CustomFieldManager;
  4. import com.atlassian.jira.issue.IssueFactory;
  5. import com.atlassian.jira.issue.MutableIssue;
  6. import com.atlassian.jira.issue.fields.CustomField;
  7. import com.atlassian.jira.web.action.JiraWebActionSupport;
  8. import com.opensymphony.util.TextUtils;
  9. import com.redradishtech.jira.ccmailer.util.CustomFieldHelperBean;
  10. import org.ofbiz.core.entity.GenericValue;
  11. import javax.mail.Address;
  12. import javax.mail.Message;
  13. import javax.mail.MessagingException;
  14. import javax.mail.internet.InternetAddress;
  15. import javax.mail.internet.MimeMessage;
  16. import java.util.HashSet;
  17. import java.util.Properties;
  18. import java.util.Set;
  19. /**
  20. * JIRA action that removes an email address from an issue's CC custom field list. The email address, CC field ID and an
  21. * authorizing token are passed in as parameters of a GET request, usually in the form of an 'unsubscribe' URL in an email
  22. * notification.
  23. * <p/>
  24. * To prevent anyone from being allowed to remove any address from a CC list, we verify that the invoker was the recipient
  25. * of a JIRA notification email involving the issue they are trying to remove a CC email from. This is done by requiring
  26. * a token parameter, which we look up in the database. In this implementation we piggy-back off JIRA's mail threading
  27. * facility, which allows lookup of an issue by token (message ID stored in the notificationinstance table).
  28. */
  29. public class UnsubscribeCCField extends JiraWebActionSupport
  30. {
  31. String unsubToken;
  32. String email;
  33. String cfId;
  34. private CustomFieldManager customFieldManager;
  35. private IssueFactory issueFactory;
  36. private String resultMessage = null;
  37. public UnsubscribeCCField(CustomFieldManager customFieldManager, IssueFactory issueFactory)
  38. {
  39. this.customFieldManager = customFieldManager;
  40. this.issueFactory = issueFactory;
  41. }
  42. protected void doValidation()
  43. {
  44. if (!TextUtils.stringSet(email))
  45. addError("email", "'email' param: Email address not specified");
  46. if (!TextUtils.stringSet(unsubToken))
  47. addError("unsubToken", "'unsubToken' param: Unsubscribe token not specified");
  48. if (!TextUtils.stringSet(cfId))
  49. addError("cfId", "'cfId' param: Custom field ID not specified");
  50. try
  51. {
  52. Long.parseLong(cfId);
  53. } catch (Exception e)
  54. {
  55. addError("cfId", "cfId must be an integer");
  56. }
  57. super.doValidation();
  58. }
  59. protected String doExecute() throws Exception
  60. {
  61. MutableIssue issue = getIssue();
  62. if (issue != null)
  63. {
  64. CustomFieldHelperBean cfHelper = new CustomFieldHelperBean(customFieldManager, log);
  65. HashSet<Address> addressHashSet = new HashSet<Address>();
  66. try
  67. {
  68. Set<InternetAddress> oldCCAddresses = cfHelper.getCustomFieldValueSet(issue, getCCCustomField());
  69. InternetAddress emailAddr = new InternetAddress(email);
  70. addressHashSet.add(emailAddr);
  71. cfHelper.removeCustomFieldValueSet(issue, getCCCustomField(), addressHashSet);
  72. if (oldCCAddresses.contains(emailAddr))
  73. {
  74. resultMessage = "removed";
  75. // resultMessage = "Removed " + TextUtils.htmlEncode(emailAddr.toString() + " from CC list of " + issue);
  76. }
  77. else
  78. {
  79. resultMessage = "notcced";
  80. // resultMessage = TextUtils.htmlEncode(emailAddr.toString() + " was not in the CC list of " + issue);
  81. }
  82. log.debug(resultMessage);
  83. } catch (MessagingException e)
  84. {
  85. addError("email", "Invalid email address: " + TextUtils.htmlEncode(email));
  86. }
  87. }
  88. else
  89. {
  90. addErrorMessage("Could not find unsubscribe token '" + TextUtils.htmlEncode(unsubToken) + "'. Check that you pasted it correctly from the email.");
  91. return ERROR;
  92. }
  93. return super.doExecute();
  94. }
  95. /**
  96. * Find the issue associated with the given unsubToken param.
  97. *
  98. * @return Issue to unsub an email from, or null if not found or token was invalid.
  99. */
  100. private MutableIssue getIssue()
  101. {
  102. MutableIssue issue = null;
  103. Message message = new MimeMessage(javax.mail.Session.getDefaultInstance(new Properties()));
  104. try
  105. {
  106. message.setHeader("In-Reply-To", unsubToken);
  107. GenericValue issueGV = ManagerFactory.getMailThreadManager().getAssociatedIssue(message);
  108. if (issueGV != null)
  109. {
  110. issue = issueFactory.getIssue(issueGV);
  111. }
  112. else
  113. {
  114. log.info("In attempt to unsubscribe " + email + ", could not find given CC unsubscribe token: " + unsubToken);
  115. }
  116. } catch (MessagingException e)
  117. {
  118. log.error("Invalid token could not be set as In-Reply-To: header value: " + unsubToken);
  119. }
  120. return issue;
  121. }
  122. public String getIssueKey()
  123. {
  124. return getIssue().getKey();
  125. }
  126. public String getUnsubToken()
  127. {
  128. return unsubToken;
  129. }
  130. public void setUnsubToken(String unsubToken)
  131. {
  132. this.unsubToken = unsubToken;
  133. }
  134. public String getEmail()
  135. {
  136. return email;
  137. }
  138. public void setEmail(String email)
  139. {
  140. this.email = email;
  141. }
  142. public String getCfId()
  143. {
  144. return cfId;
  145. }
  146. public void setCfId(String cfId)
  147. {
  148. this.cfId = cfId;
  149. }
  150. public String getResultMessage()
  151. {
  152. return resultMessage;
  153. }
  154. public CustomField getCCCustomField()
  155. {
  156. return customFieldManager.getCustomFieldObject(new Long(cfId));
  157. }
  158. }