getting error messages in script runner

BYA December 21, 2020

Hello, 

I am using issuethisemail to send mail from project A to project B with listeners using groovy from scritprunner : 

here is the script used : 

https://drive.google.com/file/d/1IAw23-34TRBsywJXlEygfvJpFU90YlJ1/view

When i run the script here is the error i got

Time (on server): Mon Dec 21 2020 21:48:20 GMT+0100 (heure normale d’Europe centrale)

The following log information was produced by this execution. Use statements like:log.info("...") to record logging information.

2020-12-21 21:48:20,711 WARN [runner.ScriptBindingsManager]: Handling issue SAN-78
2020-12-21 21:48:20,712 WARN [runner.ScriptBindingsManager]: Searching for Email in issue SAN-78
2020-12-21 21:48:20,743 WARN [runner.ScriptBindingsManager]: 2 Email found in issue SAN-78
2020-12-21 21:48:20,743 WARN [runner.ScriptBindingsManager]: emailLog {from:grdf-jdm-sandbox@demande.grdf.fr,to:grdf-jdm-bacasable@demande.grdf.fr,date:2020-12-21 21:46:59.989,source:OPERATION,subject:(SAN-78) Test Fayçal - 21h46,attachments:null}
2020-12-21 21:48:20,743 WARN [runner.ScriptBindingsManager]: emailLog {from:grdf-jdm-sandbox@demande.grdf.fr,to:grdf-jdm-bacasable@demande.grdf.fr,date:2020-12-21 21:48:20.412,source:null,subject:GRDF (SAN-78) Test Fayçal - 21h46,attachments:null}
2020-12-21 21:48:20,743 WARN [runner.ScriptBindingsManager]: 2 Email found in issue SAN-78
2020-12-21 21:48:20,744 WARN [runner.ScriptBindingsManager]: emailLog {from:grdf-jdm-sandbox@demande.grdf.fr,to:grdf-jdm-bacasable@demande.grdf.fr,date:2020-12-21 21:48:20.412,source:null,subject:GRDF (SAN-78) Test Fayçal - 21h46,attachments:null}
2020-12-21 21:48:20,744 WARN [runner.ScriptBindingsManager]: emailLog {from:grdf-jdm-sandbox@demande.grdf.fr,to:grdf-jdm-bacasable@demande.grdf.fr,date:2020-12-21 21:46:59.989,source:OPERATION,subject:(SAN-78) Test Fayçal - 21h46,attachments:null}
2020-12-21 21:48:20,744 WARN [runner.ScriptBindingsManager]: 2 Email found in issue SAN-78
2020-12-21 21:48:20,744 WARN [runner.ScriptBindingsManager]: Searching Project for email [grdf-jdm-sandbox@demande.grdf.fr]
2020-12-21 21:48:20,744 WARN [runner.ScriptBindingsManager]: Project for email [grdf-jdm-sandbox@demande.grdf.fr] is [null]
2020-12-21 21:48:20,744 WARN [runner.ScriptBindingsManager]: Searching Project for email [grdf-jdm-bacasable@demande.grdf.fr]
2020-12-21 21:48:20,744 WARN [runner.ScriptBindingsManager]: Project for email [grdf-jdm-bacasable@demande.grdf.fr] is [null]
2020-12-21 21:48:20,745 WARN [runner.ScriptBindingsManager]: emailLogemailLog {from:grdf-jdm-sandbox@demande.grdf.fr,to:grdf-jdm-bacasable@demande.grdf.fr,date:2020-12-21 21:48:20.412,source:null,subject:GRDF (SAN-78) Test Fayçal - 21h46}
srcProjectnull
srcIssueSAN-78
destProjectnull
destIssuenull
2020-12-21 21:48:20,747 WARN [runner.ScriptBindingsManager]: Evaluating - emailContext : emailLogemailLog {from:grdf-jdm-sandbox@demande.grdf.fr,to:grdf-jdm-bacasable@demande.grdf.fr,date:2020-12-21 21:48:20.412,source:null,subject:GRDF (SAN-78) Test Fayçal - 21h46}
srcProjectnull
srcIssueSAN-78
destProjectnull
destIssuenull
2020-12-21 21:48:20,749 WARN [runner.ScriptBindingsManager]: getEmailContextToManage - emailContext : emailLogemailLog {from:grdf-jdm-sandbox@demande.grdf.fr,to:grdf-jdm-bacasable@demande.grdf.fr,date:2020-12-21 21:48:20.412,source:null,subject:GRDF (SAN-78) Test Fayçal - 21h46}
srcProjectnull
srcIssueSAN-78
destProjectnull
destIssuenull
2020-12-21 21:48:20,750 WARN [runner.ScriptBindingsManager]: raisingEvent ISSUE_COMMENTED_BY_EXT_MAIL

I don't understand why i have 

- srcProject is null

- and destProject is null

can you please help, i need you help community. 

Thanks. 

BR

1 answer

1 accepted

0 votes
Answer accepted
Radek Dostál
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 21, 2020

Hi,

 

Could you put the code here in a code block? Not particularly feeling like downloading and opening a random file off the internet :)

 

Could try taking a look later on,

 

Thanks,

Radek

BYA December 22, 2020

Hello Radek,

Thanks for your anwser, I wanted to put the code but it exceeds 20,000 characters, that's why I put it on my google drive which is safe and secure. 

I will put it on several comment.

Thanks

Fayçal

BYA December 22, 2020
import java.io.File;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern; 
import org.apache.log4j.Logger;
import com.atlassian.configurable.ObjectConfigurationException;
//import com.atlassian.fugue.Either;
import io.atlassian.fugue.Either;
import com.atlassian.jira.bc.issue.IssueService;
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.component.pico.ComponentManager;
//import com.atlassian.jira.component.ComponentManager;
//import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.config.ConstantsManager;
//import com.atlassian.jira.config.util.AttachmentPathManager;
//import com.atlassian.jira.datetime.DateTimeFormatter;
//import com.atlassian.jira.datetime.DateTimeFormatterFactory;
//import com.atlassian.jira.datetime.DateTimeStyle;
import com.atlassian.jira.event.issue.IssueEvent;
import com.atlassian.jira.exception.CreateException;
import com.atlassian.jira.issue.AttachmentError;
import com.atlassian.jira.issue.AttachmentManager;
import com.atlassian.jira.issue.CustomFieldManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.IssueInputParameters;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.attachment.Attachment;
import com.atlassian.jira.issue.comments.Comment;
import com.atlassian.jira.issue.comments.CommentManager;
import com.atlassian.jira.issue.context.IssueContext;
import com.atlassian.jira.issue.customfields.manager.OptionsManager;
import com.atlassian.jira.issue.customfields.option.Option;
import com.atlassian.jira.issue.customfields.option.Options;
import com.atlassian.jira.issue.fields.CustomField;
import com.atlassian.jira.issue.fields.config.FieldConfig;
import com.atlassian.jira.issue.issuetype.IssueType;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.link.IssueLinkManager;
import com.atlassian.jira.issue.link.IssueLinkType;
import com.atlassian.jira.issue.link.IssueLinkTypeManager;
import com.atlassian.jira.project.Project;
import com.atlassian.jira.project.ProjectManager;
import com.atlassian.jira.security.JiraAuthenticationContext;
import com.atlassian.jira.service.JiraServiceContainer;
import com.atlassian.jira.service.ServiceConfigStore;
import com.atlassian.jira.user.ApplicationUser;
import com.atlassian.jira.user.util.UserManager;
import com.atlassian.jira.util.ErrorCollection;
import com.atlassian.jira.util.PathUtils;
import com.atlassian.jira.util.SimpleErrorCollection;
import com.atlassian.mail.MailException;
import com.atlassian.mail.server.MailServer;
import com.atlassian.mail.server.MailServerManager;
import com.google.common.collect.Maps;
import com.metainf.jira.plugin.emailissue.api.EmailLog;
import com.metainf.jira.plugin.emailissue.api.EmailLogQuery;
import com.metainf.jira.plugin.emailissue.api.EmailService;
import com.metainf.jira.plugin.emailissue.handler.webwork.HandlerDetailsModel;
import com.metainf.jira.plugin.emailissue.jql.AuditLogSearcher;
import com.metainf.jira.plugin.emailissue.entity.AuditLogEntry.EmailType;

import com.onresolve.scriptrunner.runner.customisers.PluginModule;
import com.onresolve.scriptrunner.runner.customisers.WithPlugin;
import com.atlassian.jira.event.issue.IssueEventBundle;
import com.atlassian.jira.event.issue.IssueEventManager;
import com.atlassian.jira.event.issue.IssueEventBundleFactory;

@WithPlugin("com.metainf.jira.plugin.emailissue")

public class MaximizedString {
private String original;
private String maximized;

public MaximizedString(String _string, int _length) {
this(_string, _length, "...");
}
public MaximizedString(String _string, int _length, String _maximizedSuffix) {
original = _string;
if (_string.length() > _length) {
maximized = _string.substring(0, _length - _maximizedSuffix.length() ) + _maximizedSuffix;
}
}

public boolean isMaximized() {
return maximized != null;
}

public String getOriginal() {
return original;
}

public String getMaximized() {
return maximized;
}
}

/**
* @FQCN fr.grdf.listener.MailHandlerCommentListener
* @author vthoule (Smartview)
* @since 1.0.0
* @version 1.0.0
* @description
*/
public class MailHandlerCommentListener {

// public static Logger log = Logger.getLogger(MailHandlerCommentListener.class);
public static Logger log = Logger.getLogger("MailHandlerCommentListener");
public static String LINK_TYPE_INTRA_PROJECT = "Lien"; // "Relates";
public static String ISSUE_TYPE_DEMANDE = "Demande";
public static String CF_MODELE_MAIL = "Modèle de mail";
public static String CF_MAIL_DEMANDEUR = "Mail du demandeur";
public static String mailDomain = "demande.grdf.fr";

public JiraAuthenticationContext jiraAuthenticationContext = ComponentAccessor.getJiraAuthenticationContext();
public ConstantsManager constantsManager = ComponentAccessor.getConstantsManager();
public ProjectManager projectManager = ComponentAccessor.getProjectManager();
public IssueManager issueManager = ComponentAccessor.getIssueManager();
public IssueLinkManager issueLinkManager = ComponentAccessor.getComponent(IssueLinkManager.class);
public IssueLinkTypeManager issueLinkTypeManager = ComponentAccessor.getComponent(IssueLinkTypeManager.class);
public CustomFieldManager customFieldManager = ComponentAccessor.getCustomFieldManager();
public OptionsManager optionsManager = ComponentAccessor.getOptionsManager();

public IssueService issueService = ComponentAccessor.getComponent(IssueService.class);

protected final UserManager userManager = ComponentAccessor.getComponent(UserManager.class);
protected final CommentManager commentManager = ComponentAccessor.getComponent(CommentManager.class);

protected final MailServerManager mailServerManager = ComponentAccessor.getComponent(MailServerManager.class);
protected final ServiceConfigStore serviceConfigStore = ComponentAccessor.getComponent(ServiceConfigStore.class);
protected final AttachmentManager attachmentManager = ComponentAccessor.getAttachmentManager();
// protected final AttachmentPathManager attachmentPathManager = ComponentManager.getAttachmentPathManager();
protected final IssueEventManager issueEventManager = ComponentAccessor.getIssueEventManager();
protected final IssueEventBundleFactory issueEventFactory = (IssueEventBundleFactory) ComponentAccessor.getComponent(IssueEventBundleFactory.class);

// protected final DateTimeFormatterFactory dateTimeFormatterFactory = ComponentManager.getComponent(DateTimeFormatterFactory.class);
private Long ISSUE_CREATED_BY_MAIL = new Long(10201L); // PP new Long(10302L);
private Long ISSUE_COMMENTED_BY_MAIL = new Long(10202L); // PP new Long(10303L);
private Long ISSUE_COMMENTED_BY_EXT_MAIL = new Long(10203L); // PP new Long(10304L);
private void raiseEvent(final Long _eventId, final ApplicationUser _user, final Issue _issue) {
IssueEventBundle eventBundle = issueEventFactory.wrapInBundle(new IssueEvent (_issue, null, _user, _eventId, true));
issueEventManager.dispatchEvent(eventBundle);
}
@PluginModule
public EmailService emailService; // = ComponentManager.getComponent(EmailService.class);

public Map<String, String> projectKeysByEmail = null;

public IssueLinkType issueLinkType;
public IssueType issueType;
public String mailUsername = "Mail";
public ApplicationUser mailUser;
public CustomField cfModeleMail;
public CustomField cfMailDemandeur;

private Comparator<Attachment> attachmentComparatorByDescDate = new Comparator<Attachment>() {
public int compare(final Attachment _attachment1, Attachment _attachment2) {
Timestamp ts1;
Timestamp ts2;
try {
ts1 = _attachment1.getCreated();
ts2 = _attachment2.getCreated();
} catch (Exception e) {
log.warn("Exeption " + e);
}
return ts2.compareTo(ts1);
}
};

/**
* @FQCN fr.grdf.listener.MailHandlerCommentListener.EmailContext
* @description Its hold details related an email, related Source/Destination for Project/Issue
*/
public class EmailContext {
private final EmailLog emailLog;
private List<Attachment> emailedAttachments;

private Issue srcIssue;
private Project srcProject;
private Project destProject;
private Issue destIssue;

public EmailContext(final Issue _issue, final EmailLog _emailLog) {
emailLog = _emailLog;
srcIssue = _issue;
//project = srcIssue.getProjectObject();

srcProject = getProjectForEmail(emailLog.getFrom());
destProject = getProjectForEmail(emailLog.getTo());

log.warn(this);
}

@Override
public String toString() {
StringBuffer toString = new StringBuffer();
String s_emailLog = "emailLog {from:${emailLog.from},to:${emailLog.to},date:${emailLog.date},source:${emailLog.source},subject:${emailLog.subject}}";
toString.append("emailLog").append(s_emailLog).append("\n");
toString.append("srcProject").append(srcProject).append("\n");
toString.append("srcIssue").append(srcIssue).append("\n");
toString.append("destProject").append(destProject).append("\n");
toString.append("destIssue").append(destIssue);

return toString.toString();
}

/**
* @return true if the mail has to be transformed in issue or comment in another project As soon as Souce and Destination Projects are
* identified and are different
*/
public boolean needConversion() {
boolean needTransformation = false;
if (forceConversion) {
needTransformation = true;
} else {
if (destProject != null) {
needTransformation = !destProject.equals(issue.project);
}
log.warn("needTransformation : ${needTransformation}");
}
return needTransformation;
}

public Project getSrcProject() {
return srcProject;
}

public Issue getSrcIssue() {
return srcIssue;
}

public Project getDestProject() {
return destProject;
}

public Issue getDestIssue() {
return destIssue;
}

public void setDestIssue(Issue destIssue) {
this.destIssue = destIssue;
}


public EmailLog getEmailLog() {
return emailLog;
}

public synchronized List<Attachment> getEmailedAttachments() {
if (emailedAttachments == null) {
log.warn("Identifying emailed Attachment in Issue [" + srcIssue.getKey() + "] ...");

emailedAttachments = new ArrayList<Attachment>();
String attachmentNames = emailLog.getAttachments();
List<String> listAttachmentNames = Arrays.asList(attachmentNames.split(","));

// List of Attachment order by descending Created date
List<Attachment> attachments = attachmentManager.getAttachments(srcIssue, attachmentComparatorByDescDate);

// Filter only latest
final Map<String, Attachment> lastAttachments = new HashMap<String, Attachment>();
for (Attachment attachment : attachments) {
if (lastAttachments.get(attachment.getFilename()) == null) {
lastAttachments.put(attachment.getFilename(), attachment);
}
}
// Identify Attachment sent by Email
for (String attachmentName : listAttachmentNames) {
Attachment attachment = lastAttachments.get(attachmentName.trim());
if (attachment != null) {
log.warn("Adding Attachment [" + attachment.getId() + "," + attachment.getFilename() + "] ...");
emailedAttachments.add(attachment);
}
}
}
return emailedAttachments;
}
}

// private DateTimeFormatter dateTimeFormatter =
// dateTimeFormatterFactory.formatter().withStyle(DateTimeStyle.ISO_8601_DATE_TIME).withSystemZone();

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");


private Comparator<EmailLog> emailLogComparatorByDateAsc = new Comparator<EmailLog>() {
public int compare(final EmailLog _emailLog0, EmailLog _emailLog1) {
Date dt1;
Date dt2;
try {
dt1 = sdf.parse(_emailLog0.getDate());
dt2 = sdf.parse(_emailLog1.getDate());
} catch (Exception e) {
log.warn("Exeption " + e);
}
return dt1.compareTo(dt2);
}
};

private Comparator<EmailLog> emailLogComparatorByDateDesc = new Comparator<EmailLog>() {
public int compare(final EmailLog _emailLog0, EmailLog _emailLog1) {
Date dt1;
Date dt2;
try {
dt1 = sdf.parse(_emailLog0.getDate());
dt2 = sdf.parse(_emailLog1.getDate());
} catch (Exception e) {
log.warn("Exeption " + e);
}
return dt2.compareTo(dt1);
}
};

public boolean enabled = true;
public boolean forceConversion = false;

private static MailHandlerCommentListener instance;

public MailHandlerCommentListener(final Logger _log) {
if (_log != null) {
log = _log;
}
refresh();
}

public void refresh() {
issueType = (IssueType) constantsManager.getIssueConstantByName(ConstantsManager.CONSTANT_TYPE.ISSUE_TYPE.getType(), ISSUE_TYPE_DEMANDE);
issueLinkType = getIssueLinkType(LINK_TYPE_INTRA_PROJECT);
cfModeleMail = getCustomFieldObjectByName(CF_MODELE_MAIL);
cfMailDemandeur = getCustomFieldObjectByName(CF_MAIL_DEMANDEUR);

log.warn("issueType = ${issueType}");
log.warn("issueLinkType = ${issueLinkType}");
log.warn("cfModeleMail = ${cfModeleMail}");
}

public static MailHandlerCommentListener getInstance(Logger _log) {
if (instance == null) {
instance = new MailHandlerCommentListener(_log);
instance.mailUsername = "JiraDemandesMetier";
instance.LINK_TYPE_INTRA_PROJECT = "Lien (Intra Projet)";
instance.ISSUE_TYPE_DEMANDE = "Demande";
instance.enabled = true;
instance.forceConversion = true;
instance.refresh();
}
return instance;
}

/**
* @param _linkTypeName
* @return IssueLinkType
*/
public IssueLinkType getIssueLinkType(String _linkTypeName) {
IssueLinkType issueLinkType = null;
Collection<IssueLinkType> issueLinkTypes = this.issueLinkTypeManager.getIssueLinkTypesByName(_linkTypeName);
if (issueLinkTypes != null && issueLinkTypes.size() == 1) {
issueLinkType = (IssueLinkType) issueLinkTypes.iterator().next();
} else {
log.error("Not able to identify an unique Issue Link Type for [" + _linkTypeName + "] " + new Object[0]);
}
return issueLinkType;
}

public CustomField getCustomFieldObjectByName(String _cfName) {
CustomField cf = null;
Collection<CustomField> cfs = customFieldManager.getCustomFieldObjectsByName(_cfName);
if (cfs != null && !cfs.isEmpty()) {
cf = cfs.iterator().next();
} else {
String errMsg = "No CustomField named [" + _cfName + "].";
log.error(errMsg);
}
return cf;
}

public ApplicationUser getMailUser() {
if (mailUser == null || !mailUser.getUsername().equals(mailUsername)) {
mailUser = userManager.getUserByName(mailUsername);
if (mailUser == null) {
log.error("User [" + mailUsername + "] does not exist !");
}
}
return mailUser;
}

final static String PATTERN_SHAREDMAIL = "(.*)@(.*)/(.*)";

/**
* @param _mailServer
* @return Mail Address used by the Mail Server. In case of Shared Mail, the real Mail is deduced.
*/
private String getEmail(final MailServer _mailServer) {
String username = _mailServer.getUsername();
Pattern p = Pattern.compile(PATTERN_SHAREDMAIL);
Matcher m = p.matcher(username);
if (m.matches()) {
if (mailDomain != null) {
return m.group(3) + "@" + mailDomain;
} else {
return m.group(3) + "@" + m.group(2);
}
} else {
return username;
}
}

/**
* Loop on all Service Configuration and search for MailFetcherService in order to extract the Mail Handler configuration. For each Mail Handler,
* - the Project is extracted from Mail Handler configuration - the email address is extracted from the used Mail Server
*
* @return a map email/projectKey
*/
private synchronized Map<String, String> getProjectKeysByEmailFromMailHandlers() {
if (projectKeysByEmail == null) {
log.warn("Loading emailAddress/Project from Mail Handler configuration ...");

projectKeysByEmail = new HashMap<String, String>();
for (Iterator<JiraServiceContainer> itServices = serviceConfigStore.getAllServiceConfigs().iterator(); itServices.hasNext();) {
JiraServiceContainer serviceContainer = itServices.next();
String serviceClassName = serviceContainer.getServiceClass();
try {
serviceClassName = serviceContainer.getServiceClass();
if (serviceClassName.equals("com.atlassian.jira.service.services.mail.MailFetcherService")) {

Long mailServerId = Long.valueOf(serviceContainer.getProperty("popserver"));
log.warn("mailServerId = ${mailServerId}");
MailServer mailServer = mailServerManager.getMailServer(mailServerId);
log.warn("mailServerName = ${mailServer.name}");

String email = getEmail(mailServer).toLowerCase();
String projectKey = projectKeysByEmail.get(email);
if (projectKey != null) {
throw new Exception("Email [" + email + "] already used in Project [" + projectKey + "] ");
}

HandlerDetailsModel details = new HandlerDetailsModel();
String handlerParams = serviceContainer.getProperty("handler.params");
log.warn("handlerParams is [${handlerParams}]");
details.fromServiceParams(handlerParams);

projectKey = details.getProjectKey();

log.warn("Caching [${email}, ${projectKey}]");
projectKeysByEmail.put(email, projectKey);
}
} catch (ObjectConfigurationException | MailException e) {
e.printStackTrace();
throw e;
}
}
}
return projectKeysByEmail;
}

// private Map<String, String> getProjectKeysByEmail() {
// if (projectKeysByEmail == null) {
// projectKeysByEmail = new HashMap<String, String>();
// for (Project project : projectManager.getProjectObjects()) {
// projectKeysByEmail.put(project.getEmail(), project.getKey());
// }
// }
// return projectKeysByEmail;
// }

/**
* @param _emailAddress
* @return the Key of the Project used by the Mail Handler with the passed email address
*/
public Project getProjectForEmail(final String _emailAddress) {
Project project = null;
log.warn("Searching Project for email [${_emailAddress}]");
List<String> emailAddresses = Arrays.asList(_emailAddress.split(","));
for (String emailAddress : emailAddresses) {
if (project == null) {
String projectKey = getProjectKeysByEmailFromMailHandlers().get(emailAddress.toLowerCase());
if (projectKey != null) {
project = projectManager.getProjectObjByKey(projectKey);
}
}
}
log.warn("Project for email [${_emailAddress}] is [${project}]");
return project;
}

/**
* @param _issue
* @return List of emails linked to the current Issue
*/
public Collection<EmailLog> getEmailLogsByType(Issue _issue, EmailType _emailType) {
Collection<EmailLog> emailLogs;
try {
EmailLogQuery emailLogQuery = new EmailLogQuery();
emailLogQuery.setIssueId(_issue.getId());
if (_emailType != null) {
emailLogQuery.setType(_emailType.name());
}
emailLogs = emailService.queryEmailLog(emailLogQuery);
} catch (Exception e) {
e.printStackTrace();
}
log.warn("${emailLogs?.size()} Email found in issue ${_issue}");
return emailLogs;
}
BYA December 22, 2020

 


public List<EmailLog> getOperationEmailLogs(Issue _issue) {
log.warn("Searching for Email in issue ${_issue}");
List<EmailLog> emailLogs = new ArrayList<EmailLog>();
//emailLogs.addAll(getEmailLogsByType(_issue, EmailType.INCOMING_ISSUE));
//emailLogs.addAll(getEmailLogsByType(_issue, EmailType.INCOMING_COMMENT));
//emailLogs.addAll(getEmailLogsByType(_issue, EmailType.OUTGOING));
emailLogs.addAll(getEmailLogsByType(_issue, null));
logEmailLogs(emailLogs);
log.warn("${emailLogs?.size()} Email found in issue ${_issue}");
Collections.sort(emailLogs, emailLogComparatorByDateDesc);
logEmailLogs(emailLogs);
log.warn("${emailLogs?.size()} Email found in issue ${_issue}");
return emailLogs;
}

public void logEmailLogs(final List<EmailLog> _emailLogs) {
for (EmailLog emailLog : _emailLogs) {
log.warn("emailLog {from:${emailLog.from},to:${emailLog.to},date:${emailLog.date},source:${emailLog.source},subject:${emailLog.subject},attachments:${emailLog.attachments}}");
}
}

private Comment convertEmailAsComment(final EmailContext _emailContext) {
Comment comment = null;
try {
ApplicationUser commentAuthor = getMailUser();
Issue issue = _emailContext.getDestIssue();
EmailLog emailLog = _emailContext.getEmailLog();
String commentMsg = emailLog.getBody();
if (enabled) {
log.warn("About to add Comment into [" + issue.getKey() + "]");
comment = commentManager.create(issue, commentAuthor, commentMsg, null, null, false);
}
} catch (Exception e) {
log.error("... Issue Comment failed...", e);
}
return comment;
}

/**
* @param _creator
* User assumed as creator of the new Issue
* @param newIssueInputParameters
* @param _comment
* @return
*/
protected Issue createIssue(final ApplicationUser _creator, final IssueInputParameters newIssueInputParameters, final String _comment) {
ErrorCollection errorCollection = new SimpleErrorCollection();
Issue createdIssue = null;
log.warn("Creating Issue with IssueInputParameters :" + newIssueInputParameters.getActionParameters());
IssueService.CreateValidationResult createValidationResult = issueService.validateCreate(_creator, newIssueInputParameters);
if (!createValidationResult.isValid()) {
errorCollection.addErrorCollection(createValidationResult.getErrorCollection());
log.error(errorCollection.toString());
} else {
createdIssue = issueService.create(_creator, createValidationResult).getIssue();
log.warn("New Issue Created: " + createdIssue.getKey());

if (_comment != null) {
IssueInputParameters updateIssueInputParameters = issueService.newIssueInputParameters();
updateIssueInputParameters.setComment(_comment);
IssueService.UpdateValidationResult updateValidationResult = issueService.validateUpdate(_creator, createdIssue.getId(), updateIssueInputParameters);
if (!updateValidationResult.isValid()) {
errorCollection.addErrorCollection(updateValidationResult.getErrorCollection());
log.error(errorCollection.toString());
} else {
Issue commentedIssue = issueService.update(_creator, updateValidationResult).getIssue();
log.warn("Issue Commented: " + commentedIssue.getKey());
}
}
}
return createdIssue;
}

public Option getDefaultOption(FieldConfig _fieldConfig, CustomField _customField) {
Option defaultOption = null;
if (_fieldConfig != null && _customField != null) {
defaultOption = (Option) _customField.getCustomFieldType().getDefaultValue(_fieldConfig);
}
return defaultOption;
}

public Option getDefaultOrFirstOption(IssueContext _issueContext, CustomField _customField) {
FieldConfig fieldConfig = _customField.getRelevantConfig(_issueContext);
Option option = getDefaultOption(fieldConfig, _customField);
if (option == null) {
Options options = optionsManager.getOptions(fieldConfig);
if (options != null) {
if (options.size() == 1) {
option = options.iterator().next();
}
}
}
return option;
}

public String getDefaultOrFirstOptionId(IssueContext _issueContext, CustomField _customField) {
String optionId = null;
Option option = getDefaultOrFirstOption(_issueContext, _customField);
if (option != null) {
optionId = option.getOptionId().toString();
}
return optionId;
}

public IssueContext getIssueContext(final Project _project, final IssueType _issueType) {
IssueContext issueContext = new IssueContext() {
public Project getProjectObject() {
return _project;
}

public Long getProjectId() {
return _project.getId();
}

public IssueType getIssueTypeObject() {
return _issueType;
}

public IssueType getIssueType() {
return _issueType;
}

public String getIssueTypeId() {
return (_issueType != null) ? _issueType.getId() : null;
}
};
return issueContext;
}

public String getDefaultOrFirstOptionId(final CustomField _customField, final Project _project, final IssueType _issueType) {
IssueContext issueContext = getIssueContext(_project, _issueType);
String optionId = getDefaultOrFirstOptionId(issueContext, _customField);
return optionId;
}

/**
* Create an Issue in Destination Project - Project is identified by the Email Context (depending on Mail Handler settings)
*
* @param _emailContext
* @return Issue created in Destination Project (identified in Email Context)
*/
private Issue convertEmailAsIssue(EmailContext _emailContext) throws Exception {
log.warn("Converting email as new Issue ...");
Issue createdIssue = null;
try {
ApplicationUser reporter = getMailUser();

IssueInputParameters newIssueInputParameters = issueService.newIssueInputParameters();

// with Regular Fields
newIssueInputParameters.setProjectId(_emailContext.getDestProject().getId());
newIssueInputParameters.setIssueTypeId(issueType.getId());

MaximizedString summary = new MaximizedString(_emailContext.getEmailLog().getSubject(), 255);
String body = _emailContext.getEmailLog().getBody();
if (summary.isMaximized()) {
newIssueInputParameters.setSummary(summary.getMaximized());
newIssueInputParameters.setDescription("Sujet = " + summary.getOriginal() + "\n" + body);
} else {
newIssueInputParameters.setSummary(summary.getOriginal());
newIssueInputParameters.setDescription(body );
}

newIssueInputParameters.setReporterId(reporter.getUsername());
newIssueInputParameters.setDescription(_emailContext.getEmailLog().getBody());
// newIssueInputParameters.setPriorityId(1l);

newIssueInputParameters.addCustomFieldValue(cfModeleMail.getIdAsLong(), getDefaultOrFirstOptionId(cfModeleMail, _emailContext.getDestProject(), null));
newIssueInputParameters.addCustomFieldValue(cfMailDemandeur.getIdAsLong(), _emailContext.getEmailLog().getFrom());

newIssueInputParameters.setSkipScreenCheck(true);
// newIssueInputParameters.setApplyDefaultValuesWhenParameterNotProvided(true);

log.warn("... into Project ${_emailContext.destProject.key} [${issueType.name}] as new Issue ...");

if (enabled) {
createdIssue = createIssue(reporter, newIssueInputParameters, null);
_emailContext.setDestIssue(createdIssue);
createIssueLink(_emailContext.getSrcIssue(), _emailContext.getDestIssue(), reporter);
}

} catch (Exception e) {
log.error("... Issue Creation failed...", e);
}
return createdIssue;
}

/**
* Create an Issue Link
*
* @param _srcIssue
* @param _destIssue
* @param _user
* @throws Exception
*/
private void createIssueLink(final Issue _srcIssue, final Issue _destIssue, final ApplicationUser _user) throws Exception {
try {
Long sequence = Long.valueOf(issueLinkManager.getOutwardLinks(_srcIssue.getId()).size());
issueLinkManager.createIssueLink(_srcIssue.getId(), _destIssue.getId(), issueLinkType.getId(), sequence, _user);
} catch (CreateException ce) {
String msgError = "Creation of Issue Link [" + issueLinkType.getName() + "] between Issue [" + _srcIssue.getKey() + "] and Issue [" + _srcIssue.getKey() + "] failed due to " + ce
.getLocalizedMessage();
log.error(msgError, ce);
throw new Exception(msgError, ce);
}
}

private void copyAttachments(final EmailContext _emailContext) {
List<Attachment> emailedAttachments = _emailContext.getEmailedAttachments();
if (!emailedAttachments.isEmpty()) {
for (Attachment attachment : emailedAttachments) {
log.warn("Copying Attachment from Issue [" + _emailContext.getSrcIssue().getKey() + "] to Issue [" + _emailContext.getDestIssue().getKey() + "] ...");
Either<AttachmentError, Attachment> result = attachmentManager.copyAttachment(attachment, getMailUser(), _emailContext.getDestIssue().getKey());
if (result.isLeft()) {
log.warn("Error on attachment Copy " + ((AttachmentError)result.left().get()).getLocalizedMessage());
} else {
log.warn("Attachment Copy successed" + ((Attachment)result.right().get()).getFilename());
}
}
}
}

/**
* Handled email requires a conversion as Issue or Comment
*
* @param _emailContext
* @throws Exception
*/
private void convertEmail(final EmailContext _emailContext) throws Exception {
log.warn("Validating Linked Issues ...");
validateLinkedIssue(_emailContext);

log.warn("Converting Email ...");
if (_emailContext.getDestIssue() == null) {
Issue issue = convertEmailAsIssue(_emailContext);
raiseEvent(ISSUE_CREATED_BY_MAIL, getMailUser(), issue);
} else {
convertEmailAsComment(_emailContext);
raiseEvent(ISSUE_COMMENTED_BY_MAIL, getMailUser(), _emailContext.getDestIssue());
}
copyAttachments(_emailContext);
}

/**
* @param _issueLinkType
* @param _issueLinks
* @return
*/
public List<IssueLink> getIssueLinksByLinkType(final IssueLinkType _issueLinkType, final List<IssueLink> _issueLinks) {
List<IssueLink> issueLinksByLinkType = new ArrayList<IssueLink>();
for (IssueLink link : _issueLinks) {
if (_issueLinkType.getId().equals(link.getIssueLinkType().getId())) {
log.warn("Matching Issue Link {src:" + link.getSourceId() + ",dest:" + link.getDestinationId() + ":linkType:{id:" + link.getIssueLinkType().getId() + ",name:" + link
.getIssueLinkType().getName() + "}}");
issueLinksByLinkType.add(link);
} else {
log.warn("Non Matching Issue Link {src:" + link.getSourceId() + ",dest:" + link.getDestinationId() + ":linkType:{id:" + link.getIssueLinkType().getId() + ",name:" + link
.getIssueLinkType().getName() + "}}");
}
}
return issueLinksByLinkType;
}

public interface IssueGetter {
public Issue getIssue(final IssueLink _issueLink);
}

public static IssueGetter issueGetterDestination = new IssueGetter() {
public Issue getIssue(final IssueLink _issueLink) {
return _issueLink.getDestinationObject();
};
};

public static IssueGetter issueGetterSource = new IssueGetter() {
public Issue getIssue(final IssueLink _issueLink) {
return _issueLink.getSourceObject();
};
};

/**
* @param _linkedIssues
* List of Linked Issues loaded with only matching Issues
* @param _project
* Project expected as Project of the valid Linked Issues
* @param _issueLinks
* Issue Links to evaluate
* @param _issueGetter
* Getter depending of Issue Link direction
*/
public void filterMatchingLinkedIssues(final List<Issue> _linkedIssues, final Project _project, final List<IssueLink> _issueLinks, final IssueGetter _issueGetter) {
List<IssueLink> issueLinks = getIssueLinksByLinkType(issueLinkType, _issueLinks);
for (IssueLink issueLink : issueLinks) {
Issue issue = _issueGetter.getIssue(issueLink);
if (_project.equals(issue.getProjectObject())) {
log.warn("... linked to [" + issue.getKey() + "]");
_linkedIssues.add(issue);
}
}
}

/**
* @param _issue
* @param _project
* @return List of all Linked Issues (only in passed Project) of the passed Issue
*/
public List<Issue> getLinkedIssuesInProject(final Issue _issue, final Project _project) {
log.warn("Search Linked Issues for {issueKey:" + _issue.getKey() + "}");
List<Issue> linkedIssues = new ArrayList<Issue>();
// log.warn("Search Linked Issues for {issueKey:" + _issue.getKey() + "} ... By filtering on Link Type = {id:" + issueLinkType.getId() + ",
// name: \"" + issueLinkType.getName() + "\"}");
log.warn("Search Linked Issues for {issueKey:" + _issue.getKey() + "} ... By filtering on Link Type = {issueLinkType:" + issueLinkType + "\"}");
filterMatchingLinkedIssues(linkedIssues, _project, issueLinkManager.getInwardLinks(_issue.getId()), issueGetterSource);
filterMatchingLinkedIssues(linkedIssues, _project, issueLinkManager.getOutwardLinks(_issue.getId()), issueGetterDestination);
log.warn("${linkedIssues?.size()} Linked Issues found !");
return linkedIssues;
}
/**
* @param _emailContext
* @throws Exception
*/
private void validateLinkedIssue(final EmailContext _emailContext) throws Exception {
log.warn("Validating Linked Issues for [${_emailContext?.getSrcIssue().key}] in Project [${_emailContext?.getDestProject().key}]...");
if (_emailContext.getDestProject() != null) {
List<Issue> linkedIssuesInProject = getLinkedIssuesInProject(_emailContext.getSrcIssue(), _emailContext.getDestProject());
if (linkedIssuesInProject.isEmpty()) {
log.warn("No Linked Issue found in Target Project ...");
} else if (linkedIssuesInProject.size() == 1) {
log.warn("Issue has a linked Issue in Project ...");
_emailContext.setDestIssue(linkedIssuesInProject.iterator().next());
} else {
throw new Exception("Issue has many linked Issue in Project");
}
log.warn("EmailContext : ${_emailContext}");
}
}
/**
* @param _emailLogs
* List of mails linked to an issue (ordered by creation date)
* @return The last email issued from an operation in JIRA (Send Mail from Issue)
*/
private EmailContext getEmailContextToManage(Issue _issue, Collection<EmailLog> _emailLogs) {
EmailContext emailContext = null;
final Iterator<EmailLog> itr = _emailLogs.iterator();
EmailLog emailLog = null;
EmailLog nextEmailLog = itr.next();
if (nextEmailLog != null) {
while (nextEmailLog != null && emailContext == null) {
emailContext = new EmailContext(_issue, nextEmailLog);
log.warn("Evaluating - emailContext : ${emailContext}");

if (!"OPERATION".equals(nextEmailLog.getSource())) {
if (emailContext.getSrcProject() != null) {
emailContext = null;
}
} else {
if (emailContext.getSrcProject() == null) {
emailContext = null;
}
}
if (emailContext == null) {
nextEmailLog = null;
if (itr.hasNext()) {
nextEmailLog = itr.next();
}
}
}
}
log.warn("getEmailContextToManage - emailContext : ${emailContext}");
return emailContext;
}
/**
* @param _emailLogs
* List of mails linked to an issue (ordered by creation date)
* @return The last email issued from an operation in JIRA (Send Mail from Issue)
*/
private EmailLog getLastEmailLog(Collection<EmailLog> _emailLogs) {
final Iterator<EmailLog> itr = _emailLogs.iterator();
EmailLog emailLog = null;
EmailLog nextEmailLog = itr.next();
if (nextEmailLog != null) {
while (nextEmailLog != null) {
if ("OPERATION".equals(nextEmailLog.getSource())) {
emailLog = nextEmailLog;
}
nextEmailLog = null;
if (itr.hasNext()) {
nextEmailLog = itr.next();
}
}
}
log.warn("Last EmailLog {from:${emailLog.from},to:${emailLog.to},date:${emailLog.date},source:${emailLog.source},subject:${emailLog.subject}}");
return emailLog;
}

public void handleEvent(final Issue _issue) {
log.warn("Handling issue ${_issue}");

// When Listener is executed by an Event initiated by Mail Handler, there is not loggedInUser in current Context.
// It causes that the permission Modify Reporter fails
ApplicationUser originalUser = jiraAuthenticationContext.getLoggedInUser();
try {
// The we switch the Logged In User in Context by using user set as Mail User
jiraAuthenticationContext.setLoggedInUser(getMailUser());
List<EmailLog> emailLogs = getOperationEmailLogs(_issue);
if (emailLogs != null && !emailLogs.isEmpty()) {
//EmailLog firstEmailLog = emailLogs.get(0);
//EmailLog lastEmailLog = emailLogs.get(emailLogs.size() - 1);
//EmailLog emailLog = lastEmailLog; // getLastEmailLog(emailLogs);
EmailContext emailContext = getEmailContextToManage(_issue, emailLogs);
if(emailContext.getEmailLog().getSource().equals("OPERATION")){
//EmailContext emailContext = new EmailContext(_issue, emailLog);
log.warn("EmailContext : ${emailContext}");
if (emailContext.needConversion()) {
log.warn("convertingEmail");
try {
convertEmail(emailContext);
} catch (Exception e) {
e.printStackTrace();
}
} else {
log.warn("No conversion required ");
}

} else {
log.warn("raisingEvent ISSUE_COMMENTED_BY_EXT_MAIL");
raiseEvent(ISSUE_COMMENTED_BY_EXT_MAIL, getMailUser(), _issue);
}
}

} catch (Exception e) {
log.error("Error", e);
e.printStackTrace();
throw e;
} finally {
jiraAuthenticationContext.setLoggedInUser(originalUser);
}
}

public void handleEvent(final IssueEvent _issueEvent) {
Issue issue = _issueEvent.getIssue();
handleEvent(issue);
}

private static void test1(Logger _log) {
MailHandlerCommentListener mhcl = new MailHandlerCommentListener(_log);
mhcl.getProjectKeysByEmailFromMailHandlers();
mhcl.mailUsername = "admin";

Issue issue = mhcl.issueManager.getIssueObject("PA-12");
List<EmailLog> emailLogs = mhcl.getOperationEmailLogs(issue);
mhcl.logEmailLogs(emailLogs);
mhcl.getLastEmailLog(emailLogs);
}

private static void test2(Logger _log) {
MailHandlerCommentListener mhcl = new MailHandlerCommentListener(_log);
mhcl.mailUsername = "admin";
mhcl.LINK_TYPE_INTRA_PROJECT = "Relates";
mhcl.ISSUE_TYPE_DEMANDE = "Tâche";
mhcl.enabled = true;
mhcl.forceConversion = true;
mhcl.refresh();
Issue issue = mhcl.issueManager.getIssueObject("PA-12");
mhcl.handleEvent(issue);
}

private static void test3(Logger _log) {
MailHandlerCommentListener mhcl = new MailHandlerCommentListener(_log);
mhcl.mailUsername = "admin";
mhcl.LINK_TYPE_INTRA_PROJECT = "Relates";
mhcl.ISSUE_TYPE_DEMANDE = "Tâche";
mhcl.enabled = false;
mhcl.forceConversion = true;
mhcl.refresh();
Issue issue = mhcl.issueManager.getIssueObject("PA-12");
mhcl.handleEvent(issue);
}

private void sample() {
IssueEvent event;
MailHandlerCommentListener mhcl = MailHandlerCommentListener.getInstance(log);
mhcl.handleEvent(event.getIssue());
}
}

MailHandlerCommentListener mhcl = MailHandlerCommentListener.getInstance(log);
//mhcl.projectKeysByEmail = null;
mhcl.handleEvent(event.issue);
//-------------------

 

Thansk for you help. 

Merci 

Fayçal

Radek Dostál
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 22, 2020

Well okay this is a little painful to go through to be perfectly honest but maybe I noticed something after staring at this in IDE for a bit - one thing seems odd at least,

 

2020-12-21 21:48:20,747 WARN [runner.ScriptBindingsManager]: Evaluating - emailContext : emailLogemailLog {from:grdf-jdm-sandbox@demande.grdf.fr,to:grdf-jdm-bacasable@demande.grdf.fr,date:2020-12-21 21:48:20.412,source:null,subject:GRDF (SAN-78) Test Fayçal - 21h46}
srcProjectnull
srcIssueSAN-78
destProjectnull
destIssuenull

Your question was why srcProject and destProject are null, so I focused on this log statement.

 

I can only find a single log statement which this comes could from, which is

emailContext = new EmailContext(_issue, nextEmailLog);
log.warn("Evaluating - emailContext : ${emailContext}");

 

Now I see this constructor

public class EmailContext {
private final EmailLog emailLog;
private List<Attachment> emailedAttachments;

private Issue srcIssue;
private Project srcProject;
private Project destProject;
private Issue destIssue;

public EmailContext(final Issue _issue, final EmailLog _emailLog) {
emailLog = _emailLog;
srcIssue = _issue;
//project = srcIssue.getProjectObject();

srcProject = getProjectForEmail(emailLog.getFrom());
destProject = getProjectForEmail(emailLog.getTo());

log.warn(this);
}

@Override
public String toString() {
...
}


public Project getSrcProject() {
return srcProject;
}

public Project getDestProject() {
return destProject;
}

...
}

 

So srcProject variable is set by this method getProjectForEmail

public Project getProjectForEmail(final String _emailAddress) {
Project project = null;
log.warn("Searching Project for email [${_emailAddress}]");
List<String> emailAddresses = Arrays.asList(_emailAddress.split(","));
for (String emailAddress : emailAddresses) {
if (project == null) {
String projectKey = getProjectKeysByEmailFromMailHandlers().get(emailAddress.toLowerCase());
if (projectKey != null) {
project = projectManager.getProjectObjByKey(projectKey);
}
}
}
log.warn("Project for email [${_emailAddress}] is [${project}]");
return project;
}

 

Where the important part is all about the projectKey -- so you pass a comma delimited String here, turn it into a List, and then for each email you try to set the projectKey variable. And so for each email address, you try to set the projectKey variable with this method:

String projectKey = getProjectKeysByEmailFromMailHandlers().get(emailAddress.toLowerCase()

 

In this function you have a WARN log statement, but it is not visible in the logs you originally attached, because your logs contain WARN statements, this should be there as well, but it isn't:

if (projectKeysByEmail == null) {
log.warn("Loading emailAddress/Project from Mail Handler configuration ...");
...
}

 

And because it is missing, it looks like the script never gets to this point. It seems like it never passes the if condition.

Which makes me think, is projectKeysByEmail variable initialized at any point, is it undefined or just always null and so this function just does nothing?

 

If I search for where this variable is set or changed, I see only a single initializer:

public class MailHandlerCommentListener {
public Map<String, String> projectKeysByEmail = null;
..
}

 But the variable never changes. So this entire function getProjectKeysByEmailFromMailHandlers never does anything.

 

Or at least I think so.

 

Anyway, if this is the exact same code as you use then that's at least what I can see which looks odd. I don't know exactly what the whole code does, I only followed the trail, but probably the way to "fix" this would be to initialize the projectKeysByEmail variable as an empty map, and change the 

if (projectKeysByEmail == null)

condition to instead check the size, i.e

if (projectKeysByEmail.size() == 0)

 

 

Although I don't know if that's just a single thing why the script doesn't work, it should explain why the srcProject is null though.

 

//R

Like BYA likes this
BYA December 23, 2020

Hello Radek, 

Is working, thank you so much . 

BR

Fayçal

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events