function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
JPClarkJPClark 

Email Enhancements help with setInline and setContentType

We're trying to send out ICS attachments for calendar requests, but we can't seem to get this new feature to work correctly.

 

Are there any examples in apex to use these changes?

Are there any special configuration changes necessary?

 

Rasmus MenckeRasmus Mencke
Do you have a sniplet of your code? I am writing some sample code I hope to post shortly for how you can do this.
JPClarkJPClark

We're using custom objects throughout, so you'll not be able to use the code, but it is self explainitory. 

Here is a test we are trying to execute:

 

public static testMethod void testSendEmail() { testSendEmailHelper('text/x-vCalendar'); testSendEmailHelper('application/x-vCalendar'); testSendEmailHelper('text/calendar'); testSendEmailHelper('application/calendar'); } private static void testSendEmailHelper(String mime){ //AppointmentController uut = new AppointmentController(testUtilities.); //testUtilities. i360_Appointment__c item = testUtilities.GetAppointment(0); // If both Reps are null, we don't send. if (item.Sales_Rep_1__c == null && item.Sales_Rep_2__c == null) return; i360_Prospect__c prospect; String rep1Email; // The email addresses for the reps. String rep2Email; if (item.Prospect__c != null) { prospect = AppointmentUtils.getProspectById(item.Prospect__c); } // Get the email addresses if not null List<String> toAddresses = new List<String>(); if (item.Sales_Rep_1__c != null) { toAddresses.add(AppointmentUtils.getStaffEmailById(item.Sales_Rep_1__c)); } if (item.Sales_Rep_2__c != null) { toAddresses.add(AppointmentUtils.getStaffEmailById(item.Sales_Rep_2__c)); } toAddresses.add('xxxxxxxx@xxxxxxxx.com'); // Set the subject. String subjectLine = ' Appointment Set for ' + item.Start__c.format() + ' ' + item.Start_Time__c; if (prospect != null) { subjectLine = prospect.Name + subjectLine; } /* // These next lines are removed since we'll be creating an Appointment Invite object and trying to send via the server ASAP. */ Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage(); email.setSubject(subjectLine); email.setToAddresses(toAddresses); email.setHtmlBody(AppointmentUtils.getNotificationBody(item.id)); email.setPlainTextBody(AppointmentUtils.getNotificationBodyText(item.id)); // Create an email attachment Messaging.EmailFileAttachment efa = new Messaging.EmailFileAttachment(); efa.setFileName('Appointment.pdf'); // set name of PDF efa.setBody(AppointmentUtils.getNotificationPDF(item.id)); //attach the PDF Messaging.EmailFileAttachment vcal = new Messaging.EmailFileAttachment(); vcal.setFileName('Appointment.ics'); vcal.setBody(AppointmentUtils.getNotificationVCal(item.id)); vcal.setContentType(mime); vcal.setInLine(true); // email.setPlainTextBody(AppointmentUtils.getNotificationVCalAsString(item.id)); email.setFileAttachments(new Messaging.EmailFileAttachment[] {efa, vcal}); //email.setFileAttachments(new Messaging.EmailFileAttachment[] {vcal}); // send it, ignoring any errors (bad!) Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email}); // Encode the doc and save. Note attach = new Note(); attach.Body = 'Email sent: ' + Date.today(); attach.Title = 'Email sent: ' + Date.today(); attach.ParentId = item.id; insert attach; }

 

 

 

 

 

 

 

Here is the ICS data in a page

 

 

<apex:page standardController="i360_Appointment__c" extensions="AppointmentNotificationController" sidebar="false" showheader="false"> BEGIN:VCALENDAR VERSION:2.0 PRODID://Improveit! 360 CRM METHOD:REQUEST BEGIN:VEVENT SEQUENCE:1 SUMMARY:{!prospect.Name} Appointment - Confirmed={!item.Confirmed__c} DESCRIPTION: {!prospect.Name} Appointment to cover {!item.Components_1__c} {!item.Components_2__c} {!item.Components_3__c} at {!item.Start_Time__c}\n{!item.Address__c} \n{!item.City__c}, {!item.State__c} {!item.Zip__c} LOCATION:{!item.Address__c} {!item.City__c}, {!item.State__c} {!item.Zip__c} CLASS:PUBLIC ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;MAILTO:{!rep1Email} ATTENDEE;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:MAILTO:{!rep2Email} UID:{!item.Id} DTSTART:{!zuluStart} DTEND:{!zuluEnd} DTSTAMP:{!zuluCreated} ORGANIZER:MAILTO:{!userEmail} END:VEVENT END:VCALENDAR </apex:page>

 

JPClarkJPClark

p.s.

It does send the email, but doesn't arrive in the expected format. In most cases, such as Outlook,  you still need to double click to open, then you can accept the meeting invitation. Doesn't work in Blackberry or gmail.

Venkat PolisettVenkat Polisett

JPClark wrote:

p.s.

It does send the email, but doesn't arrive in the expected format. In most cases, such as Outlook,  you still need to double click to open, then you can accept the meeting invitation. Doesn't work in Blackberry or gmail.


Yes. For me it is only working that way if I set the content type of the attachment to 'text/calendar'. I really want to send a meeting request that simply shows up in Outlook as meeting request and lets the invitee to accept/decline. Hope some one from Salesforce is reading this.

 

 

sforce2009sforce2009

Hi,

         I am getting the following error with the below code. Please advise..

Error: Compile Error: Method does not exist or incorrect signature: [Messaging.EmailFileAttachment].setContentType(String) at line 16 column 9

 

Code:

public class VF_Test
{
    List<String> toAddresses = new List<String>();
    public VF_Test()
    {
        toAddresses.add('sforce2009@gmail.com');
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        email.setSubject('Test');
        email.setToAddresses(toAddresses);
        email.setHtmlBody('Test');
        email.setPlainTextBody('Test');
        Messaging.EmailFileAttachment vcal = new Messaging.EmailFileAttachment();
        vcal.setFileName('Appointment.ics');
        Blob fileBody;
        vcal.setBody(fileBody);
        vcal.setContentType('text/Calendar');
        vcal.setInLine(true);
        email.setFileAttachments(new Messaging.EmailFileAttachment[] {vcal});
         Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email}); 
    }
   
}

Venkat PolisettVenkat Polisett

These new methods are only available in Winter 10. Most likely, you are trying this in your sandbox which may have Winter 10 already installed. Please verify you have Winter 10 on your sandbox. You should see a snow man with 10 in his hands.

 

If you have Winter 10 on your sandbox:

 

  • If you are using Eclipse Force.com IDE's Execute anonymous block screen to run your code, it will not run as the IDE still uses API version 16 which does not have these methods. These are only available in Version 17.
  • Try these methods from a visualforce page and apex class.

 

 


sforce2009 wrote:

Hi,

         I am getting the following error with the below code. Please advise..

Error: Compile Error: Method does not exist or incorrect signature: [Messaging.EmailFileAttachment].setContentType(String) at line 16 column 9

 

Code:

public class VF_Test
{
    List<String> toAddresses = new List<String>();
    public VF_Test()
    {
        toAddresses.add('sforce2009@gmail.com');
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        email.setSubject('Test');
        email.setToAddresses(toAddresses);
        email.setHtmlBody('Test');
        email.setPlainTextBody('Test');
        Messaging.EmailFileAttachment vcal = new Messaging.EmailFileAttachment();
        vcal.setFileName('Appointment.ics');
        Blob fileBody;
        vcal.setBody(fileBody);
        vcal.setContentType('text/Calendar');
        vcal.setInLine(true);
        email.setFileAttachments(new Messaging.EmailFileAttachment[] {vcal});
         Messaging.SendEmailResult [] r = Messaging.sendEmail(new Messaging.SingleEmailMessage[] {email}); 
    }
   
}


tolian02tolian02
Yes, that is all well and good, but I think we should directly ask the force.com people how they did it (since it was directly mentioned in the new features webinar) rather than sifting through responses that tell us tothat their IDE plugin needs to be updated.
RRESRRES
Has anyone been able to do this successfully? We've been trying now for weeks with no luck. 
JPClarkJPClark

We are also waiting for help from SalesForce to show us how to do this.

We've attempted executing this in a lookp, sending in different contentTypes and setInLine options. Nothing has worked for us yet.

 

RRESRRES

SUCCESS!!!! We finally have the code and it works. I've attached it below:

 

Controller: 

 

public class MeetingInviteController { public String sendTo { get; set; } public MeetingInviteController(ApexPages.StandardController controller) { } public PageReference sendInvite() { Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); String[] toAddresses = new String[] {sendTo}; mail.setToAddresses(toAddresses); mail.setSubject('Meeting Invitation'); mail.setPlainTextBody(''); Blob invite = Blob.valueOf('BEGIN:VCALENDAR\nPRODID:-//Microsoft Corporation//Outlook 12.0 MIMEDIR//EN\nVERSION:2.0\nMETHOD:PUBLISH\nX-MS-OLK-FORCEINSPECTOROPEN:TRUE\nBEGIN:VEVENT\nCLASS:PUBLIC\nCREATED:20091026T203709Z\nDTEND:20091028T010000Z\nDTSTAMP:20091026T203709Z\nDTSTART:20091028T000000Z\nLAST-MODIFIED:20091026T203709Z\nLOCATION:Online\nPRIORITY:5\nSEQUENCE:0\nSUMMARY;LANGUAGE=en-us:Meeting\nTRANSP:OPAQUE\nUID:4036587160834EA4AE7848CBD028D1D200000000000000000000000000000000\nX-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//E\n N"><HTML><HEAD><META NAME="Generator" CONTENT="MS Exchange Server ve\n rsion 08.00.0681.000"><TITLE></TITLE></HEAD><BODY><!-- Converted f\n rom text/plain format --></BODY></HTML>\nX-MICROSOFT-CDO-BUSYSTATUS:BUSY\nX-MICROSOFT-CDO-IMPORTANCE:1\nEND:VEVENT\nEND:VCALENDAR'); Messaging.EmailFileAttachment attach = new Messaging.EmailFileAttachment(); attach.filename = 'meeting.ics'; attach.ContentType = 'text/calendar;method=REQUEST'; attach.inline = true; attach.body = invite; mail.setFileAttachments(new Messaging.EmailFileAttachment[] { attach }); Messaging.SendEmailResult[] er = Messaging.sendEmail(new Messaging.Email[] { mail }); return null; }}

 

 Sample Page:

 

 

<apex:page standardController="Event" extensions="MeetingInviteController"> <apex:form > <apex:pageBlock > <apex:pageblockSection > Send To: <apex:inputText value="{!sendTo}"/> <apex:inputField value="{!Event.StartDateTime}" /> <apex:commandButton value="send" action="{!sendInvite}"/> </apex:pageblockSection> </apex:pageBlock> </apex:form></apex:page>

 

Make sure the attendee email in the ICS file and  the recipient email match or the user won't receive the Yes/No/Maybe options on the invite. Let me know if you have any questions.

 

 

 

jhartjhart

I was running into problems with this too.

 

You need to make sure your API client (whatever is calling your Apex method or Apex "executeAnonymous" block) is specifying a recent enough API version.

 

I double-checked and I was specifying "https://www.salesforce.com/services/Soap/u/14.0".  Changing that to https://www.salesforce.com/services/Soap/u/17.0" made the code compile & run as expected.

 

Once you've done that you can use the methods as described in the docs (note the example above actually uses direct instance variable references, which may not be supported long term as it's not in the official doc).

Message Edited by jhart on 02-04-2010 04:09 PM
hoagieryderhoagieryder

I am little confused. Where in your code did you specify the attendee?