Hi,
I want to use the ScriptRunner built-in script send custom email in order to send MS Outlook invitations.
I am already able to create an ICS-Attachment on the issue with a custom scriptrunner script. And I am able to send this attachment with the built-in script but in Outlook it would not be detected as an invitation mail.
In this stackoverflow-entry I found a hint about how to create proper Outlook invitations and I wonder if it would be possible to adopt this somehow.
Kind Regards,
Christian
Hi Jamie,
thank you for the hint! Kind of helpful was also the recipes area (Validating Attachments/Links in Transitions) of the script runner docs.
I had to fiddle around quite a while but combining the SR docs with another stackoverflow-entry was actually the breakthrough.
Here is what I put in the Condition and Configuration area of the Send a custom email post-function:
import com.atlassian.jira.component.ComponentAccessor import org.apache.log4j.Logger import org.apache.log4j.Level import java.io.File import javax.activation.DataHandler; import javax.mail.util.ByteArrayDataSource; import javax.mail.internet.MimeBodyPart import javax.mail.internet.MimeMultipart import javax.mail.internet.MimeUtility def log = Logger.getLogger("my.company.SendOutlookInvitation") log.setLevel(Level.DEBUG) log.debug("#####################################") def last_attachment = issue.attachments.last() def file_name = last_attachment.filename.toString() def file_type = last_attachment.mimetype.toString() def file_id = last_attachment.id log.debug("FILE_NAME: " + file_name) log.debug("FILE_TYPE: " + file_type) def attachmentPathManager = ComponentAccessor.getAttachmentPathManager().attachmentPath.toString() def projectKey = issue.getProjectObject().getKey() def file_path = attachmentPathManager + "/" + projectKey + "/" + issue.key + "/" + file_id + "/" log.debug("FILE_PATH: " + file_path) File f = new File(file_path); if(f.exists() && !f.isDirectory()) { mail.addHeader("method", "REQUEST"); mail.addHeader("charset", "UTF-8"); mail.addHeader("component", "VEVENT"); log.debug("FILE_EXISTS: YES") log.debug("FILE_TEXT:" + f.text) def mp = new MimeMultipart("alternative") def calendarPart = new MimeBodyPart() calendarPart.setHeader("Content-Class", "urn:content- classes:calendarmessage"); calendarPart.setHeader("Content-ID", "calendar_message"); calendarPart.setDataHandler(new DataHandler(new ByteArrayDataSource(f.text, "text/calendar"))); mp.addBodyPart(calendarPart) mail.setMultipart(mp) } else { log.debug("FILE_EXISTS: NO") } log.debug("#####################################") true
I do not have to include any attachments with the general post-function config. This will be handled by this configuration script completely.
The above scripts expects that a proper ics file is already attached to the issue or will be attached during the current transition (in my case another SR script using the attachmentManager). In this second case the mail has to be send at the end of the post-functions so that attaching has already been performed.
Now the mail appears perfectly as an Outlook invitation
Nice job... minor thing, I'm not sure that's the best way to get the attachment file. If the issue has been moved that may not work IIRC.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thank you! In my case the attachment will be created on the same transition with first post function using another script - so in my case it could not happen that the attachment location would not fit to the issue key.
But I put a warning regarding this handling/precondition and maybe for other cases someone else finds a more robust implementation
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Christian and Jamie, Thanks for posting this! This was almost exactly what I needed. I was able to build on Christian's example above and now have a single block of code that injects a temporary attachment into a scriptrunner "send a custom email" post function to deliver an ics calendar invitation / reminder to an assignee for a task.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Matthew,
Would you mind sharing your script to inject the temporary ICS attachment?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This code should get you going.
This requires a custom field to hold a UUID. Jamie explains how to create a UUID in https://community.atlassian.com/t5/JIRA-Core-questions/How-can-I-generate-a-UUID-and-assign-to-a-custom-field/qaq-p/324170 I added this uuid creation script as a post script on the create transition for my workflow.
Note: This solution is for MS Outlook Client recipients. This will need modifications for the iCal syntax if your intended recipient uses a different mail client
I use this block in the Condition and Configuration section :
import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.Issue import com.atlassian.jira.issue.util.DefaultIssueChangeHolder import com.atlassian.jira.issue.issuetype.IssueType import com.atlassian.jira.issue.IssueImpl import com.atlassian.jira.issue.IssueFieldConstants.* import org.apache.log4j.Logger import org.apache.log4j.Level import java.text.SimpleDateFormat; import javax.activation.DataHandler; import javax.mail.util.ByteArrayDataSource; import javax.mail.internet.MimeBodyPart import javax.mail.internet.MimeMultipart import javax.mail.internet.MimeUtility def log = Logger.getLogger("company.com.SendOutlookInvitation") log.setLevel(Level.WARN) log.debug("#####################################") def optionsManager = ComponentAccessor.getOptionsManager() def customFieldManager = ComponentAccessor.getCustomFieldManager() def fieldName1 = "Custom Start DateTime" def field1 = customFieldManager.getCustomFieldObjectByName(fieldName1).getValue(issue) log.debug("Custom Start DateTime: " + field1) def fieldName2 = "Custom End DateTime" def field2 = customFieldManager.getCustomFieldObjectByName(fieldName2).getValue(issue) log.debug("Custom End DateTime: " + field1)
def fieldName3 = "Custom UUID"
def field3 = customFieldManager.getCustomFieldObjectByName(fieldName3).getValue(issue)
def fieldName4 = "Change Type"
def field4 = customFieldManager.getCustomFieldObjectByName(fieldName4).getValue(issue)
def busystatus = "BUSY"
if (field4.toString() == "Free") {
busystatus = "FREE"
} def summary = issue.getSummary() def description = issue.getDescription() def issueowner = issue.getAssigneeId() def uuid = field3.toString()
def starttimeValue = field1 def endtimeValue = field2 TimeZone tz = TimeZone.getTimeZone ("Etc/GMT") SimpleDateFormat outsdf = new SimpleDateFormat ("yyyyMMdd'T'HHmmss'Z'"); SimpleDateFormat insdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.S"); Date starttime = insdf.parse("${starttimeValue}"); outsdf.setTimeZone (tz); def UTCstarttime = outsdf.format(starttime) Date endtime = insdf.parse("${endtimeValue}"); outsdf.setTimeZone (tz); def UTCendtime = outsdf.format(endtime) outsdf.setTimeZone (tz); Calendar currentcal = Calendar.getInstance(tz) Date currenttime = currentcal.getTime() def UTCcurrenttime = outsdf.format(currenttime) //change METHOD:PUBLISH to make it automatic //change METHOD:REQUEST to make it provide buttons def iCal = """BEGIN:VCALENDAR PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN VERSION:2.0 METHOD:REQUEST X-MS-OLK-FORCEINSPECTOROPEN:TRUE BEGIN:VEVENT CLASS:PUBLIC CREATED:${UTCcurrenttime} DESCRIPTION:${description} DTEND:${UTCendtime} DTSTAMP:${UTCcurrenttime} DTSTART:${UTCstarttime} LAST-MODIFIED:${UTCcurrenttime} LOCATION:Company Name PRIORITY:5 SEQUENCE:0 SUMMARY;LANGUAGE=en-us:${summary} TRANSP:OPAQUE UID:${uuid} X-MICROSOFT-CDO-BUSYSTATUS:${busystatus} X-MICROSOFT-CDO-IMPORTANCE:1 X-MICROSOFT-DISALLOW-COUNTER:FALSE X-MS-OLK-AUTOFILLLOCATION:FALSE X-MS-OLK-CONFTYPE:0 BEGIN:VALARM TRIGGER:-PT15M ACTION:DISPLAY DESCRIPTION:Reminder END:VALARM END:VEVENT END:VCALENDAR""" mail.addHeader("method", "REQUEST"); mail.addHeader("charset", "UTF-8"); mail.addHeader("component", "VEVENT"); log.debug("FILE_EXISTS: YES") log.debug("FILE_TEXT:" + iCal) def mp = new MimeMultipart("alternative") def calendarPart = new MimeBodyPart() calendarPart.setHeader("Content-Class", "urn:content- classes:calendarmessage"); calendarPart.setHeader("Content-ID", "calendar_message"); calendarPart.setDataHandler(new DataHandler(new ByteArrayDataSource(iCal, "text/calendar"))); mp.addBodyPart(calendarPart) mail.setMultipart(mp) log.debug("#####################################") true
Then in the Email template section, I use this block:
Dear ${issue.assignee?.displayName}, <p></p> The ${issue.issueType.name} ${issue.key} with summary ${issue.summary} has been scheduled. <p></p> Description: $issue.description <p></p> <% if (mostRecentComment) out << "Last comment: " << mostRecentComment %> <p></p> CustomFieldName: <% out << issue.getCustomFieldValue( com.atlassian.jira.component.ComponentAccessor.getCustomFieldManager().getCustomFieldObjectByName("CustomFieldName") ) %> <p></p> Regards,<br></br> ${issue.reporter?.displayName}
The Subject template section gets this block:
Scheduled $issue $issue.summary
I select the HTML format and add the appropriate recipients.
The important portion of this is to choose "New" for the Include Attachments section, otherwise your temporary attachment that is built in the Condition and Configuration section will not get added to the email.
Good Luck!
-edit: We needed the ability to denote Free vs Busy in the appt, so we added a custom field that would toggle this in the ICS file.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Wow, thank you! This has been incredible! This is probably the most thorough & effective response I've ever received on Atlassian.
I used your script almost verbatim & it returns no errors. I've substituted my 3 custom fields (Custom Start Date Time - PresentationStart, Custom End Date Time - PresentationEnd, Custom UUID - UUID) and used a post function in a previous transition to populate the UUID field just like Jamie indicated.
For some reason although the post-function says 'No failures in last -- executions', the email does not send, and the Attachments field in the preview is 'null'
I feel like I'm very close & already appreciate your help tremendously; any ideas on why it may not be sending though?
Thanks!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
The attachment field in the preview is null for me as well, but it still attaches to the issue.
Something that I overlooked early in my trials was the last line of the Condition and Configuration section. The single line with the word 'true' as in the example is required or the email is not sent because it is the resultant return code of the condition block. The execution must reach this point or the condition evaluates to false and won't send.
If you really meant 'No failures in last -- executions' and didn't just redact the number of executions, it is possible that your post-function is not being executed. I try to go back to the basic steps in troubleshooting, is your workflow published? , are you certain your custom workflow is attached to the correct issue type in your workflow scheme? ...
I would suggest changing the debug level from WARN to DEBUG and then watch your catalina.out file for debugging messages. You might need to add some additional log.debug statements to determine where it is failing in the conditional execution.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You are correct - the problem was that this post function was step #1 in this transition for me. Once I moved it to the last step, it works now.
HUGE shoutout to you Matthew - thanks for the innovative solution!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Christian Schlaefcke, I really tried making this work- with no success. can you please explain how you created the ICS-Attachment on the issue with a custom scriptrunner script.
thanks
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Well, it´s been a while but as I am quite good organized I managed to find the script :-) Here you go:
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.attachment.CreateAttachmentParamsBean
import com.atlassian.jira.issue.CustomFieldManager
import java.io.BufferedWriter
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.sql.Timestamp
import java.util.UUID
import org.apache.log4j.Logger
import org.apache.log4j.Level
def log = Logger.getLogger("CreateICSAttachment")
log.setLevel(Level.DEBUG)
def attachmentManager = ComponentAccessor.getAttachmentManager()
def user = ComponentAccessor.getJiraAuthenticationContext()?.getUser()
def rendererManager = ComponentAccessor.getRendererManager()
def fieldLayoutItem = ComponentAccessor.getFieldLayoutManager().getFieldLayout(issue).getFieldLayoutItem("comment")
def renderer = rendererManager.getRendererForField(fieldLayoutItem)
def templateText = '''\
BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN
VERSION:2.0
METHOD:REQUEST
X-MS-OLK-FORCEINSPECTOROPEN:TRUE
BEGIN:VTIMEZONE
TZID:W. Europe Standard Time
BEGIN:STANDARD
DTSTART:${CREATION_TIME}
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
ATTENDEE;CN="${ORGANIZER}";RSVP=TRUE:mailto:${ORGANIZER_MAIL}
ATTENDEE;CN="${DEPLOYER}":mailto:${DEPLOYER_MAIL}
CLASS:PUBLIC
CREATED:${CREATION_TIME}
DESCRIPTION:${DESCRIPTION}\n
DTEND;TZID="W. Europe Standard Time":${END_TIME}
DTSTAMP:${CREATION_TIME}
DTSTART;TZID="W. Europe Standard Time":${START_TIME}
LAST-MODIFIED:${MOD_TIME}
LOCATION:${LOCATION}
ORGANIZER;CN="${ORGANIZER}";RSVP=TRUE:mailto:${ORGANIZER_MAIL}
PRIORITY:5
SEQUENCE:0
SUMMARY;LANGUAGE=de-ch:${SUMMARY}
TRANSP:OPAQUE
UID:${UID}
X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//E
N"><HTML><HEAD><META NAME="Generator" CONTENT="MS Exchange Server version
14.02.5004.000"><TITLE></TITLE></HEAD><BODY><!-- Converted from text/rtf
format -->${DESCRIPTION_HTML}<P DIR=LTR><SPAN LANG="de-ch"></SPAN></P></B
ODY></HTML>
X-MICROSOFT-CDO-BUSYSTATUS:BUSY
X-MICROSOFT-CDO-IMPORTANCE:1
X-MICROSOFT-DISALLOW-COUNTER:FALSE
X-MS-OLK-APPTSEQTIME:${CREATION_TIME}
X-MS-OLK-AUTOFILLLOCATION:FALSE
X-MS-OLK-CONFTYPE:0
END:VEVENT
END:VCALENDAR'''
def template = new groovy.text.StreamingTemplateEngine().createTemplate(templateText)
Calendar cal = Calendar.getInstance()
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'")
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd'T'HHmmss")
def customFieldManager = ComponentAccessor.getComponent(CustomFieldManager)
def cfDeploymentTime = customFieldManager.getCustomFieldObjectByName("Deployment Time")
Timestamp cfDeploymentTimeVal = (Timestamp) issue.getCustomFieldValue(cfDeploymentTime)
def cfDeploymentDuration = customFieldManager.getCustomFieldObjectByName("Deployment Duration")
int cfDeploymentDurationVal = (int) issue.getCustomFieldValue(cfDeploymentDuration)
log.info("START_TIME: " + sdf2.format(cfDeploymentTimeVal))
Timestamp endTime = new Timestamp(cfDeploymentTimeVal.getTime() + (cfDeploymentDurationVal * 60 * 1000))
log.info("END_TIME: " + sdf2.format(endTime))
String organizer = issue.reporter.getDisplayName()
String organizerMail = issue.reporter.getEmailAddress()
String deployer = issue.assignee.getDisplayName()
String deployerMail = issue.assignee.getEmailAddress()
String description = issue.description = (null) ? '':issue.description
String descriptionHtml = renderer.render(description, null)
descriptionHtml = descriptionHtml.replaceAll("\\n", "\\\\n")
String descriptionHtmlWrapped = ""
int index = 0
int lineLength = 80
while (index < descriptionHtml.length()) {
descriptionHtmlWrapped += descriptionHtml.substring(index, Math.min(index + lineLength,descriptionHtml.length())) + "\n\t";
index += lineLength;
}
log.info("DESCRIPTION: " + descriptionHtmlWrapped)
def binding = [
UID : UUID.randomUUID(),
CREATION_TIME : sdf1.format(cal.getTime()),
MOD_TIME : sdf1.format(cal.getTime()),
START_TIME : sdf2.format(cfDeploymentTimeVal),
END_TIME : sdf2.format(endTime),
ORGANIZER : organizer,
ORGANIZER_MAIL : organizerMail,
DEPLOYER : deployer,
DEPLOYER_MAIL : deployerMail,
LOCATION : '',
SUMMARY : issue.summary,
DESCRIPTION : description,
DESCRIPTION_HTML : descriptionHtmlWrapped
]
String attachmentContent = template.make(binding)
File attachment = new File("<PATH_TO_JIRA_INST_DIR>/temp/sample.ics")
// if file doesnt exists, then create it
if (!attachment.exists()) {
log.info("CREATING NEW ATTACHMENT!!!")
attachment.createNewFile();
}
try {
log.info("POPULATING ATTACHMENT ...")
FileWriter fw = new FileWriter(attachment.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
bw.write(attachmentContent);
bw.close();
log.info("... POPULATING ATTACHMENT - DONE!!!")
} catch(IOException exc) {
log.error("ATTACHMENT COULD NOT BE CREATED!!!", exc)
}
log.info("ADDING ATTACHMENT ...")
def bean = new CreateAttachmentParamsBean.Builder()
.file(attachment)
.filename(issue.summary + ".ics")
.contentType("text/plain")
.author(user)
.issue(issue)
.build()
attachmentManager.createAttachment(bean)
log.info("... ADDING ATTACHMENT - DONE!!!")
I hope that you can make it working for you case. Please let me know if you have any further questions.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
so so sorry for the late response and thank yo so much for posting this!
what do you mean in your text when it is written: CREATION_TIME? - Im stuck on that ):
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @roniz
the CREATION_TIME a placeholder in the template, represented by
def templateText = '''\
...
CREATED:${CREATION_TIME}
...
END:VCALENDAR'''
The placeholder in the template needs to be mapped with something useful which is happening in the binding section:
def binding = [
...
CREATION_TIME : sdf1.format(cal.getTime()),
...
]
And finally the template will be processed for filling up all placeholders with the content of the binding:
String attachmentContent = template.make(binding)
Next I am writing the attachmentContent to a file on the disk and attach it to the JIRA issue.
I hope I was able to explain the core of the implementation in a comprehensive way.
Best Regards,
Christian
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Exactly the same way like the CREATION_TIME - on-the-fly in the template/binding without CF:
def binding = [
UID : UUID.randomUUID(),
...
]
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Christian Schlaefcke, I really tried, hope it is not out of my scope..
I made a new screen +workflow + etc to match to your definitions in the code (see screenshot attached) but when I try to create a ticket I get the following error:
Error creating issue: Property 'CREATION_TIME' not found
how do I define a property?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @roniz,
where are you located? Do you have a Skype or whatever account? I think the stuff you´re having trouble with is a bit off-topic here. I would like to help and to share my knowledge but this seem to be more efficient in a 1:1 session. What do you think?
Best Regards,
Christian
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Christian Schlaefckethat would be super awsom- my skype is Roni Zeilig- Sapiens
and my mail is roni.zeilig@sapiens.com
thanks so so much!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Christian Schlaefcke or @Matthew Harkins , any idea why (after working beautifully for a year or so) now the ICS turns out as "not supported calendar message"?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This is not occurring for me.
I think that the answer to your question is that you may have updated your Outlook Client software or MS Exchange Server. Newer versions of Outlook and Exchange handle the RDATE and RRULE fields of the ics file differently than previous versions.
Also there is a bug in a particular version of MS Exchange 2016 regarding the parsing of VTIMEZONE
See the following MS support bug notice --
In @Christian Schlaefcke 's example he included an RRULE, but no RDATE. This appears to be supported by the RFC, but I do not know if Outlook is complaining about the RRULE itself (Outlook only supports a subset of possible RRULEs) or the absence of the RDATE field when an RRULE is supplied.
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
Recurrence every Year on the last Sunday of the 3rd Month - Counting days backwards could be a problem
See the following MS support article --
See the following patterns are broken in Outlook--
Some of these broken recurrence patterns and options are;
Under some circumstances, Meeting Updates or Cancelation messages could also end up broken;
Also See the following broken patterns --
1. Exceptions for weekends
2. Recur monthly: xth day counting from the backward of month
In this case, it is not broken but unable to count backward so display wrong dates in MS Outlook.
From: https://www.systoolsgroup.com/updates/fix-outlook-not-supported-calendar-message-ics-issue/
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Matthew Harkins , what a great and highly appreciated answer.
Below you can find the details on the "non-supported" ICS.
Could it be the TRIGGER:-PT15M?
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Microsoft Corporation//Outlook 14.0 MIMEDIR//EN
METHOD:REQUEST
X-MS-OLK-FORCEINSPECTOROPEN:TRUE
BEGIN:VEVENT
CLASS:PUBLIC
CREATED:20190624T092030Z
DESCRIPTION:Keine weiteren Hinweise oder Informationen zur Abwesenheit übermittelt.
DTEND:20190805T220000Z
DTSTAMP:20190624T092030Z
DTSTART:20190721T220000Z
LAST-MODIFIED:20190624T092030Z
ORGANIZER;CN=Lastname, Firstname:MAILTO:abc.def@abc.de
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=TENTATIVE;CN=CN=Lastname, Firstname:MAILTO:abc.def@abc.de
PRIORITY:5
SEQUENCE:0
SUMMARY;LANGUAGE=de-de:Urlaub - Muerle, Tilman: 22.07.2019 - 05.08.2019 (11.0 Tage) - ABC-123
TRANSP:OPAQUE
STATUS:TENTATIVE
UID:eb573c5c-ced3-4799-a5a1-b199ec8c7bb7
TRANSP:TRANSPARENT
X-MICROSOFT-CDO-BUSYSTATUS:FREE
X-MICROSOFT-CDO-IMPORTANCE:1
X-MICROSOFT-DISALLOW-COUNTER:FALSE
X-MS-OLK-AUTOFILLLOCATION:FALSE
X-MS-OLK-CONFTYPE:0
BEGIN:VALARM
TRIGGER:-PT15M
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
END:VEVENT
END:VCALENDAR
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I could not find any relevant support article referencing the TRIGGER value.
There are just a few differences I note between your "non-supported" ICS and a working ICS from my system.
You have defined the TRANSP twice with opposing values. Please try your ICS again removing one of the contradictory settings (TRANSP:OPAQUE or TRANSP:TRANSPARENT).
If that does not solve the non-supported ICS problem, I would focus on the other differences:
ORGANIZER, ATTENDEE, STATUS
You might try removing these fields one at a time to see if that resolves the problem.
If none of those changes solve the problem, then I would check your MS Exchange routing. We have another service that sends similar ICS which recently started appearing as non-supported. We currently think that this may be due to an older internal MS Exchange server that routes mail to the new upgraded primary MS Exchange server that hosts the destination mailboxes. This other service is configured to use the older MS Exchange server as its smtp endpoint. I am curious if you are also in the process of upgrading your Exchange infrastructure and have your environment configured in a similar way with Jira configured to use an older version of MS Exchange wherein your mailboxes have been migrated to a host with a newer MS Exchange version. We are operating in this manner for only a short time to allow for incremental migration as services are adjusted in turn from using the older MS Exchange host to using the more recent versioned MS Exchange host. I expect to see the non-supported ics clear up for us once this additional service is configured to use the newer versioned MS Exchange endpoint.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
@Matthew Harkins sorry to jump in on this thread! I've just tried out your code and although a mail gets sent it's just sending as a mail not a meeting invite, is there anything else that needs to be configured or that I haven't done? The only difference from your code is I set the busystatus to be BUSY all the time, would there be any other bits of the script I would need to change?
Thanks,
Eimear :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
This solution worked well for me but I had some problems with Outlook in Office 365. The email invitations were not being recognised and the email just looked like an ordinary email (no RSVP buttons), and there was no ICS file attached.
I changed one line from
calendarPart.setDataHandler(new DataHandler(new ByteArrayDataSource(iCal,
"text/calendar")));
To
calendarPart.setDataHandler(new DataHandler(new ByteArrayDataSource(iCal, "text/calendar;method=REQUEST;name=\"meeting.ics\"")));
Initial tests look good and both Outlook and Gmail receive valid invitations.
Chris
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Nice work @Chris Dunne _Raledo_! I can second your fix. This enabled usable ical notifications for our o365 users and continued to function normally for our on premises users.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You have full control over the Mail object, so you should be able to do it. The closest thing in the docs is https://scriptrunner.adaptavist.com/latest/jira/builtin-scripts.html#_adding_generated_attachments.
In the linked SO.com answer it says outlook ignores the ICS attachment. So you need to create and add a new mail part of type "text/calendar" with the contents of the ics file.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Jamie Echlin, @Matthew Harkins, @Christian Schlaefcke- great post!!
I tried making this work, unfortunately with out much success:
import com.atlassian.jira.component.ComponentAccessor
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def cf = customFieldManager.getCustomFieldObjectByName("UUID")
issue.setCustomFieldValue(cf, UUID.randomUUID().toString())
"Custom Start DateTime"--> "Estimated start time"
"Custom End DateTime" --> "Estimated complition time"
"Custom UUID" --> "UUID"
all the rest is the same
I did not do any thing with a ICS file- sould I?
and it did not work ):
Any thoughts please?
Many many thanks in advance!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Christian,
Would you share the script you used to create an ICS file and attach it to the issue?
Thanks,
Connor
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I like Matthews scripts works well - but how do I set the filename?
In Mac's Mail.app its becoming "Mail Attachment" and people cant see its an invite
Worksbetter in GMail.
BR,
Normann
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.