This is a somewhat old thread, but since I got it all working, its baked a 
while now, and I see a ton of "how do I send outlook invites" with no workable 
responses, I wanted to share since people here have helped me immensely. It's 
time to give back!

I'm on RT 4.0.4, but I think it'll work on older versions since the code I 
changed has been around a while.

A little history:

>> What I need to do is set the Content-Type as: text/calendar; 
>> charset="utf-8"; method=REQUEST

>> Anyone more entrenched in the code able to point me in the right 
>> direction? It'd be great if there was some way to just pass the value 
>> after Content-Type: in the template to the email...

Thomas Sibley wrote back:
> The part that forces text/plain is line 205 in RT::Action::SendEmail (and 
> calls into
> RT::I18N::IsTextualContentType).  The restriction to 
> m{^(?:text/(?:plain|html)|message/rfc822)\b}i
> dates from 2007, and I suspect it should be rewritten to allow arbitrary 
> content-types.

This was the ticket (ha, pun). I copied /opt/rt4/lib/RT/I18N.pm and its I18N 
supporting folder (didn't work if I didn't copy the folder/contents too) to 
/opt/rt4/local/lib/RT.

I changed this routine around line 196 in I18N.pm:
sub IsTextualContentType {
    my $type = shift;
    ($type =~ m{^(?:text/(?:plain|html|calendar)|message/rfc822)\b}i) ? 1 : 0;
}

Basically, just adding the "calendar" check to the regex.

Since everyone's scrip usage will be different, I'm not putting mine in here. 
I'm just checking on a queue change to see if this field has value (it's not 
required) or if this CF has changed (so it can send an update) once in the 
queue. Pretty basic scrip.

After the code change, I was able to build a template that would send an 
invite. The invite is sent with the meeting time pulled from a date-time custom 
field (CF #19 in my RT). I've fixed a lot of the fields in our case because 
these are really just placeholders for us (ie: they're set to 30 min lengths 
because I don't care about having to adjust the lengths and a 15 min prior 
notification time). You could easily modify those using other custom fields in 
your setup.

I've also stripped down the vCal lines to keep this simple... things like 
timezones, required/optional users, etc are all removed. If you put in the 
"required" lines, people's responses will send back vCal garbage to the 
organizer if it's not an outlook user (RT in my case) since outlook defaults to 
"Send response".

I learned almost all of the vCal stuff by sending myself some invites to an 
account I don't use outlook with and saving the email, opening it in a text 
editor, and running it through an online base64 decoder. I'm NOT attempting to 
do multi-part messages like Outlook sends. I didn't need to.

I've seen some people fix the UID field. I decided to use the ticket number 
since it's unique and this way, meetings will "update" even if the subject of 
the email/ticket changes.

If the below doesn't give you the accept/tentative/decline buttons, then there 
is a stray LF somewhere. This was the hardest part during my testing - it 
required remembering to use ctrl-enter instead of just the enter key when 
typing things out. If there was a stray LF somewhere, it would show as an 
attached .ics file or nothing at all.

Template:

Name: Send Calendar Invite
Desc: Sends outlook calendar invite
Type: perl
Content:

Content-Type: text/calendar; charset="utf-8"; method=REQUEST 

BEGIN:VCALENDAR
METHOD:REQUEST
PRODID:Microsoft Exchange Server 2007
VERSION:2.0
BEGIN:VEVENT
ORGANIZER;CN=RT:MAILTO:myrtem...@domain.com
DESCRIPTION;LANGUAGE=en-US:See Ticket 
{RT->Config->Get('WebURL')}Ticket/Display.html?id={$Ticket->id} 
 \n\nDescription of the action to 
perform:\n{$Ticket->FirstCustomFieldValue(11);} 
SUMMARY;LANGUAGE=en-US:subject
DTSTART:{ my $duedate = RT::Date->new($RT::SystemUser);
 $duedate->Set(Format=>'ISO', Value =>$Ticket->FirstCustomFieldValue(19));
 $duedate = $duedate->AsString(Format=>'iCal');
 $duedate;
}
DTEND:{
 my $newdate = RT::Date->new($RT::SystemUser);
 $newdate->Set(Format=>'ISO', Value => $Ticket->FirstCustomFieldValue(19) );
 $newdate->AddSeconds(+1800);
 $newdate = $newdate->AsString(Format=>'iCal');
 $newdate;
 }
UID:{$Ticket->id}
CLASS:PUBLIC
PRIORITY:5
DTSTAMP:{ my $now = RT::Date->new($RT::SystemUser);
 $now->SetToNow();
 $now = $now->AsString(Format=>'iCal');
 $now;
}
TRANSP:OPAQUE
STATUS:CONFIRMED
SEQUENCE:0
LOCATION;LANGUAGE=en-US:EPS
BEGIN:VALARM
ACTION:DISPLAY
DESCRIPTION:REMINDER
TRIGGER;RELATED=START:-PT15M
END:VALARM
END:VEVENT
END:VCALENDAR

When this comes to an Outlook or iphone-via-exchange user, it works great. Some 
of our droid users have "always send reply" turned on so it inserts all the 
vCal text into the ticket. Once identified, we have them turn that off. Another 
option would be to set the meeting organizer as one of your Outlook users (ie: 
a project manager).

Would be awesome if a forthcoming version of RT included that "calendar" 
content-type check.

Cheers,
Brent

Reply via email to